<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Glide,">










<meta name="description" content="序言 本文章不介绍Glide的使用方法，如标题所示，只对Glide首次加载流程进行分析，不包含缓存原理分析 只对Glide.with(context).load(url).into(imageView);进行分析。 文章会使用步骤来说明，但是经常有步骤之间的跳转，所以必要的同学可以打开两个页面，一个专门用来顺序查看，一个用来跳转步骤查看 写这篇文章的时候，最新版本就是Glide4.8.0，想看源码">
<meta name="keywords" content="Glide">
<meta property="og:type" content="article">
<meta property="og:title" content="Glide(1)-基于Glide4.8源码的首次加载流程">
<meta property="og:url" content="https://lt19931203.github.io/2019/02/11/Glide(1)-基于Glide4.8源码的首次加载流程/index.html">
<meta property="og:site_name" content="LiuTao">
<meta property="og:description" content="序言 本文章不介绍Glide的使用方法，如标题所示，只对Glide首次加载流程进行分析，不包含缓存原理分析 只对Glide.with(context).load(url).into(imageView);进行分析。 文章会使用步骤来说明，但是经常有步骤之间的跳转，所以必要的同学可以打开两个页面，一个专门用来顺序查看，一个用来跳转步骤查看 写这篇文章的时候，最新版本就是Glide4.8.0，想看源码">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2019-02-21T12:58:36.594Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Glide(1)-基于Glide4.8源码的首次加载流程">
<meta name="twitter:description" content="序言 本文章不介绍Glide的使用方法，如标题所示，只对Glide首次加载流程进行分析，不包含缓存原理分析 只对Glide.with(context).load(url).into(imageView);进行分析。 文章会使用步骤来说明，但是经常有步骤之间的跳转，所以必要的同学可以打开两个页面，一个专门用来顺序查看，一个用来跳转步骤查看 写这篇文章的时候，最新版本就是Glide4.8.0，想看源码">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":true,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://lt19931203.github.io/2019/02/11/Glide(1)-基于Glide4.8源码的首次加载流程/">





  <title>Glide(1)-基于Glide4.8源码的首次加载流程 | LiuTao</title>
  








</head>

<body itemscope="" itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope="" itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">LiuTao</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">Android开发者</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope="" itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://lt19931203.github.io/2019/02/11/Glide(1)-基于Glide4.8源码的首次加载流程/">

    <span hidden itemprop="author" itemscope="" itemtype="http://schema.org/Person">
      <meta itemprop="name" content="lt19931203">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope="" itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="LiuTao">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">Glide(1)-基于Glide4.8源码的首次加载流程</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-02-11T10:32:58+08:00">
                2019-02-11
              </time>
            

            

            
          </span>

          

          
            
          

          
          
             <span id="/2019/02/11/Glide(1)-基于Glide4.8源码的首次加载流程/" class="leancloud_visitors" data-flag-title="Glide(1)-基于Glide4.8源码的首次加载流程">
               <span class="post-meta-divider">|</span>
               <span class="post-meta-item-icon">
                 <i class="fa fa-eye"></i>
               </span>
               
                 <span class="post-meta-item-text">阅读次数&#58;</span>
               
                 <span class="leancloud-visitors-count"></span>
             </span>
          

          
            <span class="post-meta-divider">|</span>
            <span class="page-pv"><i class="fa fa-file-o"></i>
            <span class="busuanzi-value" id="busuanzi_value_page_pv"></span>
            </span>
          

          
            <div class="post-wordcount">
              
                
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                  <span class="post-meta-item-text">字数统计&#58;</span>
                
                <span title="字数统计">
                  17.3k
                </span>
              

              

              
            </div>
          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1 id="序言"><a href="#序言" class="headerlink" title="序言"></a>序言</h1><ol>
<li>本文章不介绍Glide的使用方法，如标题所示，只对Glide首次加载流程进行分析，不包含缓存原理分析</li>
<li>只对<code>Glide.with(context).load(url).into(imageView);</code>进行分析。</li>
<li>文章会使用步骤来说明，但是经常有步骤之间的跳转，所以必要的同学可以打开两个页面，一个专门用来顺序查看，一个用来跳转步骤查看</li>
<li>写这篇文章的时候，最新版本就是Glide4.8.0，想看源码的同学，直接在项目中<code>implementation &#39;com.github.bumptech.glide:glide:4.8.0&#39;</code>如果依赖最新的代码，可能会不同步</li>
<li>本人原创，转载请注明原地址</li>
</ol>
<h1 id="Glide-with"><a href="#Glide-with" class="headerlink" title="Glide.with()"></a>Glide.with()</h1><a id="more"></a>
<h2 id="步骤1：Glide-with-返回了什么"><a href="#步骤1：Glide-with-返回了什么" class="headerlink" title="步骤1：Glide.with()返回了什么"></a>步骤1：Glide.with()返回了什么</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Glide</span> <span class="keyword">implements</span> <span class="title">ComponentCallbacks2</span> </span>&#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> RequestManager <span class="title">with</span><span class="params">(@NonNull Activity activity)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> getRetriever(activity).get(activity);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> RequestManager <span class="title">with</span><span class="params">(@NonNull android.app.Fragment fragment)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> getRetriever(fragment.getActivity()).get(fragment);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> RequestManager <span class="title">with</span><span class="params">(@NonNull Context context)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> getRetriever(context).get(context);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> RequestManager <span class="title">with</span><span class="params">(@NonNull Fragment fragment)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> getRetriever(fragment.getActivity()).get(fragment);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> RequestManager <span class="title">with</span><span class="params">(@NonNull FragmentActivity activity)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> getRetriever(activity).get(activity);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> RequestManager <span class="title">with</span><span class="params">(@NonNull View view)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> getRetriever(view.getContext()).get(view);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> RequestManagerRetriever <span class="title">getRetriever</span><span class="params">(@Nullable Context context)</span> </span>&#123;</span><br><span class="line">        Preconditions.checkNotNull(context,.....);</span><br><span class="line">        <span class="keyword">return</span> Glide.get(context).getRequestManagerRetriever();</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上方贴的是部分<code>Glide.with()</code>的部分代码，这里看到内部都是调用了<code>getRetriever()</code>方法返回<code>RequestManagerRetriever</code>对象，继而调用<code>RequestManagerRetriever#get()</code>方法，返回一个<code>RequestManager</code>对象，直接进入<code>RequestManager</code>查看<code>get()</code>方法</p>
<h2 id="步骤2：RequestManager-get"><a href="#步骤2：RequestManager-get" class="headerlink" title="步骤2：RequestManager#get()"></a>步骤2：RequestManager#get()</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RequestManagerRetriever</span> <span class="keyword">implements</span> <span class="title">Handler</span>.<span class="title">Callback</span> </span>&#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="function"><span class="keyword">private</span> RequestManager <span class="title">getApplicationManager</span><span class="params">(@NonNull Context context)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (applicationManager == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (<span class="keyword">this</span>) &#123;</span><br><span class="line">                <span class="keyword">if</span> (applicationManager == <span class="keyword">null</span>) &#123;</span><br><span class="line">                    Glide glide = Glide.get(context.getApplicationContext());</span><br><span class="line">                    applicationManager = factory.build(</span><br><span class="line">                            glide,</span><br><span class="line">                            <span class="keyword">new</span> ApplicationLifecycle(),</span><br><span class="line">                            <span class="keyword">new</span> EmptyRequestManagerTreeNode(),</span><br><span class="line">                            context.getApplicationContext());</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> applicationManager;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> RequestManager <span class="title">get</span><span class="params">(@NonNull Context context)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (context == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"You cannot start a load on a null Context"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (Util.isOnMainThread() &amp;&amp; !(context <span class="keyword">instanceof</span> Application)) &#123;</span><br><span class="line">            <span class="keyword">if</span> (context <span class="keyword">instanceof</span> FragmentActivity) &#123;</span><br><span class="line">                <span class="keyword">return</span> get((FragmentActivity) context);</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (context <span class="keyword">instanceof</span> Activity) &#123;</span><br><span class="line">                <span class="keyword">return</span> get((Activity) context);</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (context <span class="keyword">instanceof</span> ContextWrapper) &#123;</span><br><span class="line">                <span class="keyword">return</span> get(((ContextWrapper) context).getBaseContext());</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> getApplicationManager(context);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> RequestManager <span class="title">get</span><span class="params">(@NonNull FragmentActivity activity)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (Util.isOnBackgroundThread()) &#123;</span><br><span class="line">            <span class="keyword">return</span> get(activity.getApplicationContext());</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            assertNotDestroyed(activity);</span><br><span class="line">            FragmentManager fm = activity.getSupportFragmentManager();</span><br><span class="line">            <span class="keyword">return</span> supportFragmentGet(activity, fm, <span class="comment">/*parentHint=*/</span> <span class="keyword">null</span>, isActivityVisible(activity));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> RequestManager <span class="title">get</span><span class="params">(@NonNull Fragment fragment)</span> </span>&#123;</span><br><span class="line">        Preconditions.checkNotNull(fragment.getActivity(),</span><br><span class="line">                <span class="string">"You cannot start a load on a fragment before it is attached or after it is destroyed"</span>);</span><br><span class="line">        <span class="keyword">if</span> (Util.isOnBackgroundThread()) &#123;</span><br><span class="line">            <span class="keyword">return</span> get(fragment.getActivity().getApplicationContext());</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            FragmentManager fm = fragment.getChildFragmentManager();</span><br><span class="line">            <span class="keyword">return</span> supportFragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> RequestManager <span class="title">get</span><span class="params">(@NonNull Activity activity)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (Util.isOnBackgroundThread()) &#123;</span><br><span class="line">            <span class="keyword">return</span> get(activity.getApplicationContext());</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            assertNotDestroyed(activity);</span><br><span class="line">            android.app.FragmentManager fm = activity.getFragmentManager();</span><br><span class="line">            <span class="keyword">return</span> fragmentGet(activity, fm, <span class="comment">/*parentHint=*/</span> <span class="keyword">null</span>, isActivityVisible(activity));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> RequestManager <span class="title">get</span><span class="params">(@NonNull View view)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (Util.isOnBackgroundThread()) &#123;</span><br><span class="line">            <span class="keyword">return</span> get(view.getContext().getApplicationContext());</span><br><span class="line">        &#125;</span><br><span class="line">        Preconditions.checkNotNull(view);</span><br><span class="line">        Preconditions.checkNotNull(view.getContext(),</span><br><span class="line">                <span class="string">"Unable to obtain a request manager for a view without a Context"</span>);</span><br><span class="line">        Activity activity = findActivity(view.getContext());</span><br><span class="line">        <span class="keyword">if</span> (activity == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> get(view.getContext().getApplicationContext());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (activity <span class="keyword">instanceof</span> FragmentActivity) &#123;</span><br><span class="line">            Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);</span><br><span class="line">            <span class="keyword">return</span> fragment != <span class="keyword">null</span> ? get(fragment) : get(activity);</span><br><span class="line">        &#125;</span><br><span class="line">        android.app.Fragment fragment = findFragment(view, activity);</span><br><span class="line">        <span class="keyword">if</span> (fragment == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> get(activity);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> get(fragment);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">private</span> RequestManager <span class="title">supportFragmentGet</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">            @NonNull Context context,</span></span></span><br><span class="line"><span class="function"><span class="params">            @NonNull FragmentManager fm,</span></span></span><br><span class="line"><span class="function"><span class="params">            @Nullable Fragment parentHint,</span></span></span><br><span class="line"><span class="function"><span class="params">            <span class="keyword">boolean</span> isParentVisible)</span> </span>&#123;</span><br><span class="line">        SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint, isParentVisible);</span><br><span class="line">        RequestManager requestManager = current.getRequestManager();</span><br><span class="line">        <span class="keyword">if</span> (requestManager == <span class="keyword">null</span>) &#123;</span><br><span class="line">            Glide glide = Glide.get(context);</span><br><span class="line">            requestManager = factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);</span><br><span class="line">            current.setRequestManager(requestManager);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> requestManager;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">private</span> RequestManager <span class="title">fragmentGet</span><span class="params">(@NonNull Context context,</span></span></span><br><span class="line"><span class="function"><span class="params">                                       @NonNull android.app.FragmentManager fm,</span></span></span><br><span class="line"><span class="function"><span class="params">                                       @Nullable android.app.Fragment parentHint,</span></span></span><br><span class="line"><span class="function"><span class="params">                                       <span class="keyword">boolean</span> isParentVisible)</span> </span>&#123;</span><br><span class="line">        RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);</span><br><span class="line">        RequestManager requestManager = current.getRequestManager();</span><br><span class="line">        <span class="keyword">if</span> (requestManager == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="comment">// TODO(b/27524013): Factor out this Glide.get() call.</span></span><br><span class="line">            Glide glide = Glide.get(context);</span><br><span class="line">            requestManager =</span><br><span class="line">                    factory.build(</span><br><span class="line">                            glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);</span><br><span class="line">            current.setRequestManager(requestManager);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> requestManager;</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>同样是贴了部分代码，看着多，其实我们可以把<code>Fragment</code>，<code>Activity</code>，<code>View</code>归为一类，剩下的<code>Application</code>归为另一类，</p>
<ol>
<li>以<code>Activity</code>为例，跳过次要逻辑直接看第61行，<code>return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));</code>调用了<code>fragmentGet()</code>方法，来到<code>fragmentGet()</code>第106行，<code>getRequestManagerFragment</code>方法返回了一个<code>Fragment</code>对象，接着初始化了<code>RequestManager</code>对象，并且构建了<code>Fragment</code>和<code>RequestManager</code>对象的关联。</li>
<li>传入<code>Application</code>时，从23行开始判断<code>Context</code>类型，最终，到31行，<code>getApplicationManager(context);</code>从3-17行看出，没有构建<code>Fragment</code>对象，而是直接用的<code>Application</code>的生命周期</li>
</ol>
<p>从这边开始，<code>Glide.with()</code>方法就分析结束了，继续分析<code>load()</code>方法</p>
<h1 id="Glide-with-load"><a href="#Glide-with-load" class="headerlink" title="Glide.with().load()"></a>Glide.with().load()</h1><h2 id="步骤3：RequestManager-load"><a href="#步骤3：RequestManager-load" class="headerlink" title="步骤3：RequestManager#load()"></a>步骤3：RequestManager#load()</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RequestManager</span> <span class="keyword">implements</span> <span class="title">LifecycleListener</span>, <span class="title">ModelTypes</span>&lt;<span class="title">RequestBuilder</span>&lt;<span class="title">Drawable</span>&gt;&gt; </span>&#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="function"><span class="keyword">public</span> RequestBuilder&lt;Drawable&gt; <span class="title">load</span><span class="params">(@Nullable Drawable drawable)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> asDrawable().load(drawable);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> RequestBuilder&lt;Drawable&gt; <span class="title">load</span><span class="params">(@Nullable Bitmap bitmap)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> asDrawable().load(bitmap);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> RequestBuilder&lt;Drawable&gt; <span class="title">load</span><span class="params">(@Nullable String string)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> asDrawable().load(string);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> RequestBuilder&lt;Drawable&gt; <span class="title">load</span><span class="params">(@RawRes @DrawableRes @Nullable Integer resourceId)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> asDrawable().load(resourceId);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> RequestBuilder&lt;Drawable&gt; <span class="title">asDrawable</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> as(Drawable.class);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">public</span> &lt;ResourceType&gt; <span class="function">RequestBuilder&lt;ResourceType&gt; <span class="title">as</span><span class="params">(@NonNull Class&lt;ResourceType&gt; resourceClass)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> RequestBuilder&lt;&gt;(glide, <span class="keyword">this</span>, resourceClass, context);</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>从步骤2知道<code>with()</code>方法返回了<code>RequestManager</code>对象，所以看<code>RequestManager#load()</code>方法， <code>load()</code>方法中默认调用了<code>asDrawable()</code>方法，第15行得知<code>asDrawable()</code>方法返回了一个<code>RequestBuilder</code>对象，之后继续调用<code>RequestBuilder#load()</code>方法，继续来查看步骤4</p>
<h2 id="步骤4-：RequestBuilder-load"><a href="#步骤4-：RequestBuilder-load" class="headerlink" title="步骤4 ：RequestBuilder#load()"></a>步骤4 ：RequestBuilder#load()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">public class RequestBuilder&lt;TranscodeType&gt; implements Cloneable,</span><br><span class="line">    ModelTypes&lt;RequestBuilder&lt;TranscodeType&gt;&gt; &#123;</span><br><span class="line">	...</span><br><span class="line">	public RequestBuilder&lt;TranscodeType&gt; load(@Nullable String string) &#123;</span><br><span class="line">		return loadGeneric(string);</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	private RequestBuilder&lt;TranscodeType&gt; loadGeneric(@Nullable Object model) &#123;</span><br><span class="line">		this.model = model;</span><br><span class="line">		isModelSet = true;</span><br><span class="line">		return this;</span><br><span class="line">	&#125;</span><br><span class="line">	...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里省略了<code>load()</code>的其他重载方法，我们着重看一下传入参数为String的时候发生了什么，第5行，<code>load()</code>方法中调用<code>loadGeneric()</code>，而<code>loadGeneric()</code>方法中就做了一些赋值操作，然后就直接返回了，可见<code>load()</code>方法依旧没有做太多事情，因为大部分的逻辑都在<code>into()</code>方法中处理了，继续往下看</p>
<h1 id="Glide-with-load-into"><a href="#Glide-with-load-into" class="headerlink" title="Glide.with().load().into()"></a>Glide.with().load().into()</h1><h2 id="步骤5：RequestBuilder-into"><a href="#步骤5：RequestBuilder-into" class="headerlink" title="步骤5：RequestBuilder#into()"></a>步骤5：RequestBuilder#into()</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RequestBuilder</span>&lt;<span class="title">TranscodeType</span>&gt; <span class="keyword">implements</span> <span class="title">Cloneable</span>,</span></span><br><span class="line"><span class="class">            <span class="title">ModelTypes</span>&lt;<span class="title">RequestBuilder</span>&lt;<span class="title">TranscodeType</span>&gt;&gt; </span>&#123;</span><br><span class="line">	...</span><br><span class="line">        <span class="function"><span class="keyword">public</span> ViewTarget&lt;ImageView, TranscodeType&gt; <span class="title">into</span><span class="params">(@NonNull ImageView view)</span> </span>&#123;</span><br><span class="line">            Util.assertMainThread();</span><br><span class="line">            Preconditions.checkNotNull(view);</span><br><span class="line">            RequestOptions requestOptions = <span class="keyword">this</span>.requestOptions;</span><br><span class="line">            <span class="keyword">if</span> (!requestOptions.isTransformationSet()</span><br><span class="line">                    &amp;&amp; requestOptions.isTransformationAllowed()</span><br><span class="line">                    &amp;&amp; view.getScaleType() != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">switch</span> (view.getScaleType()) &#123;</span><br><span class="line">                    <span class="keyword">case</span> CENTER_CROP:</span><br><span class="line">                        requestOptions = requestOptions.clone().optionalCenterCrop();</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    <span class="keyword">case</span> CENTER_INSIDE:</span><br><span class="line">                        requestOptions = requestOptions.clone().optionalCenterInside();</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    <span class="keyword">case</span> FIT_CENTER:</span><br><span class="line">                    <span class="keyword">case</span> FIT_START:</span><br><span class="line">                    <span class="keyword">case</span> FIT_END:</span><br><span class="line">                        requestOptions = requestOptions.clone().optionalFitCenter();</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    <span class="keyword">case</span> FIT_XY:</span><br><span class="line">                        requestOptions = requestOptions.clone().optionalCenterInside();</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    <span class="keyword">case</span> CENTER:</span><br><span class="line">                    <span class="keyword">case</span> MATRIX:</span><br><span class="line">                    <span class="keyword">default</span>:</span><br><span class="line">                        <span class="comment">// Do nothing.</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> into(</span><br><span class="line">                    glideContext.buildImageViewTarget(view, transcodeClass),</span><br><span class="line">		<span class="comment">/*targetListener=*/</span></span><br><span class="line">                    <span class="keyword">null</span>,</span><br><span class="line">                    requestOptions);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">private</span> &lt;Y extends Target&lt;TranscodeType&gt;&gt; <span class="function">Y <span class="title">into</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">                @NonNull Y target,</span></span></span><br><span class="line"><span class="function"><span class="params">                @Nullable RequestListener&lt;TranscodeType&gt; targetListener,</span></span></span><br><span class="line"><span class="function"><span class="params">                @NonNull RequestOptions options)</span> </span>&#123;</span><br><span class="line">            Util.assertMainThread();</span><br><span class="line">            Preconditions.checkNotNull(target);</span><br><span class="line">            <span class="keyword">if</span> (!isModelSet) &#123;</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"You must call #load() before calling #into()"</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            options = options.autoClone();</span><br><span class="line">            Request request = buildRequest(target, targetListener, options);</span><br><span class="line">            Request previous = target.getRequest();</span><br><span class="line">            <span class="keyword">if</span> (request.isEquivalentTo(previous)</span><br><span class="line">                    &amp;&amp; !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) &#123;</span><br><span class="line">                request.recycle();</span><br><span class="line">                <span class="keyword">if</span> (!Preconditions.checkNotNull(previous).isRunning()) &#123;</span><br><span class="line">                    previous.begin();</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">return</span> target;</span><br><span class="line">            &#125;</span><br><span class="line">            requestManager.clear(target);</span><br><span class="line">            target.setRequest(request);</span><br><span class="line">            requestManager.track(target, request);</span><br><span class="line">            <span class="keyword">return</span> target;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="function"><span class="keyword">private</span> Request <span class="title">buildRequest</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">                Target&lt;TranscodeType&gt; target,</span></span></span><br><span class="line"><span class="function"><span class="params">                @Nullable RequestListener&lt;TranscodeType&gt; targetListener,</span></span></span><br><span class="line"><span class="function"><span class="params">                RequestOptions requestOptions)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> buildRequestRecursive(</span><br><span class="line">                    target,</span><br><span class="line">                    targetListener,</span><br><span class="line">		<span class="comment">/*parentCoordinator=*/</span></span><br><span class="line">                    <span class="keyword">null</span>,</span><br><span class="line">                    transitionOptions,</span><br><span class="line">                    requestOptions.getPriority(),</span><br><span class="line">                    requestOptions.getOverrideWidth(),</span><br><span class="line">                    requestOptions.getOverrideHeight(),</span><br><span class="line">                    requestOptions);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="function"><span class="keyword">private</span> Request <span class="title">buildRequestRecursive</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">                Target&lt;TranscodeType&gt; target,</span></span></span><br><span class="line"><span class="function"><span class="params">                @Nullable RequestListener&lt;TranscodeType&gt; targetListener,</span></span></span><br><span class="line"><span class="function"><span class="params">                @Nullable RequestCoordinator parentCoordinator,</span></span></span><br><span class="line"><span class="function"><span class="params">                TransitionOptions&lt;?, ? <span class="keyword">super</span> TranscodeType&gt; transitionOptions,</span></span></span><br><span class="line"><span class="function"><span class="params">                Priority priority,</span></span></span><br><span class="line"><span class="function"><span class="params">                <span class="keyword">int</span> overrideWidth,</span></span></span><br><span class="line"><span class="function"><span class="params">                <span class="keyword">int</span> overrideHeight,</span></span></span><br><span class="line"><span class="function"><span class="params">                RequestOptions requestOptions)</span> </span>&#123;</span><br><span class="line">            ErrorRequestCoordinator errorRequestCoordinator = <span class="keyword">null</span>;</span><br><span class="line">            <span class="keyword">if</span> (errorBuilder != <span class="keyword">null</span>) &#123;</span><br><span class="line">                errorRequestCoordinator = <span class="keyword">new</span> ErrorRequestCoordinator(parentCoordinator);</span><br><span class="line">                parentCoordinator = errorRequestCoordinator;</span><br><span class="line">            &#125;</span><br><span class="line">            Request mainRequest =</span><br><span class="line">                    buildThumbnailRequestRecursive(</span><br><span class="line">                            target,</span><br><span class="line">                            targetListener,</span><br><span class="line">                            parentCoordinator,</span><br><span class="line">                            transitionOptions,</span><br><span class="line">                            priority,</span><br><span class="line">                            overrideWidth,</span><br><span class="line">                            overrideHeight,</span><br><span class="line">                            requestOptions);</span><br><span class="line">            <span class="keyword">if</span> (errorRequestCoordinator == <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> mainRequest;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">int</span> errorOverrideWidth = errorBuilder.requestOptions.getOverrideWidth();</span><br><span class="line">            <span class="keyword">int</span> errorOverrideHeight = errorBuilder.requestOptions.getOverrideHeight();</span><br><span class="line">            <span class="keyword">if</span> (Util.isValidDimensions(overrideWidth, overrideHeight)</span><br><span class="line">                    &amp;&amp; !errorBuilder.requestOptions.isValidOverride()) &#123;</span><br><span class="line">                errorOverrideWidth = requestOptions.getOverrideWidth();</span><br><span class="line">                errorOverrideHeight = requestOptions.getOverrideHeight();</span><br><span class="line">            &#125;</span><br><span class="line">            Request errorRequest = errorBuilder.buildRequestRecursive(</span><br><span class="line">                    target,</span><br><span class="line">                    targetListener,</span><br><span class="line">                    errorRequestCoordinator,</span><br><span class="line">                    errorBuilder.transitionOptions,</span><br><span class="line">                    errorBuilder.requestOptions.getPriority(),</span><br><span class="line">                    errorOverrideWidth,</span><br><span class="line">                    errorOverrideHeight,</span><br><span class="line">                    errorBuilder.requestOptions);</span><br><span class="line">            errorRequestCoordinator.setRequests(mainRequest, errorRequest);</span><br><span class="line">            <span class="keyword">return</span> errorRequestCoordinator;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="function"><span class="keyword">private</span> Request <span class="title">buildThumbnailRequestRecursive</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">                Target&lt;TranscodeType&gt; target,</span></span></span><br><span class="line"><span class="function"><span class="params">                RequestListener&lt;TranscodeType&gt; targetListener,</span></span></span><br><span class="line"><span class="function"><span class="params">                @Nullable RequestCoordinator parentCoordinator,</span></span></span><br><span class="line"><span class="function"><span class="params">                TransitionOptions&lt;?, ? <span class="keyword">super</span> TranscodeType&gt; transitionOptions,</span></span></span><br><span class="line"><span class="function"><span class="params">                Priority priority,</span></span></span><br><span class="line"><span class="function"><span class="params">                <span class="keyword">int</span> overrideWidth,</span></span></span><br><span class="line"><span class="function"><span class="params">                <span class="keyword">int</span> overrideHeight,</span></span></span><br><span class="line"><span class="function"><span class="params">                RequestOptions requestOptions)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">if</span> (thumbnailBuilder != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="comment">// Recursive case: contains a potentially recursive thumbnail request builder.</span></span><br><span class="line">                <span class="keyword">if</span> (isThumbnailBuilt) &#123;</span><br><span class="line">                    <span class="keyword">throw</span> <span class="keyword">new</span> IllegalStateException(<span class="string">"You cannot use a request as both the main request and a "</span></span><br><span class="line">                            + <span class="string">"thumbnail, consider using clone() on the request(s) passed to thumbnail()"</span>);</span><br><span class="line">                &#125;</span><br><span class="line">                TransitionOptions&lt;?, ? <span class="keyword">super</span> TranscodeType&gt; thumbTransitionOptions =</span><br><span class="line">                        thumbnailBuilder.transitionOptions;</span><br><span class="line">                <span class="keyword">if</span> (thumbnailBuilder.isDefaultTransitionOptionsSet) &#123;</span><br><span class="line">                    thumbTransitionOptions = transitionOptions;</span><br><span class="line">                &#125;</span><br><span class="line">                Priority thumbPriority = thumbnailBuilder.requestOptions.isPrioritySet()</span><br><span class="line">                        ? thumbnailBuilder.requestOptions.getPriority() : getThumbnailPriority(priority);</span><br><span class="line">                <span class="keyword">int</span> thumbOverrideWidth = thumbnailBuilder.requestOptions.getOverrideWidth();</span><br><span class="line">                <span class="keyword">int</span> thumbOverrideHeight = thumbnailBuilder.requestOptions.getOverrideHeight();</span><br><span class="line">                <span class="keyword">if</span> (Util.isValidDimensions(overrideWidth, overrideHeight)</span><br><span class="line">                        &amp;&amp; !thumbnailBuilder.requestOptions.isValidOverride()) &#123;</span><br><span class="line">                    thumbOverrideWidth = requestOptions.getOverrideWidth();</span><br><span class="line">                    thumbOverrideHeight = requestOptions.getOverrideHeight();</span><br><span class="line">                &#125;</span><br><span class="line">                ThumbnailRequestCoordinator coordinator = <span class="keyword">new</span> ThumbnailRequestCoordinator(parentCoordinator);</span><br><span class="line">                Request fullRequest =</span><br><span class="line">                        obtainRequest(</span><br><span class="line">                                target,</span><br><span class="line">                                targetListener,</span><br><span class="line">                                requestOptions,</span><br><span class="line">                                coordinator,</span><br><span class="line">                                transitionOptions,</span><br><span class="line">                                priority,</span><br><span class="line">                                overrideWidth,</span><br><span class="line">                                overrideHeight);</span><br><span class="line">                isThumbnailBuilt = <span class="keyword">true</span>;</span><br><span class="line">                <span class="comment">// Recursively generate thumbnail requests.</span></span><br><span class="line">                Request thumbRequest =</span><br><span class="line">                        thumbnailBuilder.buildRequestRecursive(</span><br><span class="line">                                target,</span><br><span class="line">                                targetListener,</span><br><span class="line">                                coordinator,</span><br><span class="line">                                thumbTransitionOptions,</span><br><span class="line">                                thumbPriority,</span><br><span class="line">                                thumbOverrideWidth,</span><br><span class="line">                                thumbOverrideHeight,</span><br><span class="line">                                thumbnailBuilder.requestOptions);</span><br><span class="line">                isThumbnailBuilt = <span class="keyword">false</span>;</span><br><span class="line">                coordinator.setRequests(fullRequest, thumbRequest);</span><br><span class="line">                <span class="keyword">return</span> coordinator;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (thumbSizeMultiplier != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="comment">// Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.</span></span><br><span class="line">                ThumbnailRequestCoordinator coordinator = <span class="keyword">new</span> ThumbnailRequestCoordinator(parentCoordinator);</span><br><span class="line">                Request fullRequest =</span><br><span class="line">                        obtainRequest(</span><br><span class="line">                                target,</span><br><span class="line">                                targetListener,</span><br><span class="line">                                requestOptions,</span><br><span class="line">                                coordinator,</span><br><span class="line">                                transitionOptions,</span><br><span class="line">                                priority,</span><br><span class="line">                                overrideWidth,</span><br><span class="line">                                overrideHeight);</span><br><span class="line">                RequestOptions thumbnailOptions = requestOptions.clone()</span><br><span class="line">                        .sizeMultiplier(thumbSizeMultiplier);</span><br><span class="line">                Request thumbnailRequest =</span><br><span class="line">                        obtainRequest(</span><br><span class="line">                                target,</span><br><span class="line">                                targetListener,</span><br><span class="line">                                thumbnailOptions,</span><br><span class="line">                                coordinator,</span><br><span class="line">                                transitionOptions,</span><br><span class="line">                                getThumbnailPriority(priority),</span><br><span class="line">                                overrideWidth,</span><br><span class="line">                                overrideHeight);</span><br><span class="line">                coordinator.setRequests(fullRequest, thumbnailRequest);</span><br><span class="line">                <span class="keyword">return</span> coordinator;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="comment">// Base case: no thumbnail.</span></span><br><span class="line">                <span class="keyword">return</span> obtainRequest(</span><br><span class="line">                        target,</span><br><span class="line">                        targetListener,</span><br><span class="line">                        requestOptions,</span><br><span class="line">                        parentCoordinator,</span><br><span class="line">                        transitionOptions,</span><br><span class="line">                        priority,</span><br><span class="line">                        overrideWidth,</span><br><span class="line">                        overrideHeight);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="function"><span class="keyword">private</span> Request <span class="title">obtainRequest</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">                Target&lt;TranscodeType&gt; target,</span></span></span><br><span class="line"><span class="function"><span class="params">                RequestListener&lt;TranscodeType&gt; targetListener,</span></span></span><br><span class="line"><span class="function"><span class="params">                RequestOptions requestOptions,</span></span></span><br><span class="line"><span class="function"><span class="params">                RequestCoordinator requestCoordinator,</span></span></span><br><span class="line"><span class="function"><span class="params">                TransitionOptions&lt;?, ? <span class="keyword">super</span> TranscodeType&gt; transitionOptions,</span></span></span><br><span class="line"><span class="function"><span class="params">                Priority priority,</span></span></span><br><span class="line"><span class="function"><span class="params">                <span class="keyword">int</span> overrideWidth,</span></span></span><br><span class="line"><span class="function"><span class="params">                <span class="keyword">int</span> overrideHeight)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> SingleRequest.obtain(</span><br><span class="line">                    context,</span><br><span class="line">                    glideContext,</span><br><span class="line">                    model,</span><br><span class="line">                    transcodeClass,</span><br><span class="line">                    requestOptions,</span><br><span class="line">                    overrideWidth,</span><br><span class="line">                    overrideHeight,</span><br><span class="line">                    priority,</span><br><span class="line">                    target,</span><br><span class="line">                    targetListener,</span><br><span class="line">                    requestListeners,</span><br><span class="line">                    requestCoordinator,</span><br><span class="line">                    glideContext.getEngine(),</span><br><span class="line">                    transitionOptions.getTransitionFactory());</span><br><span class="line">        &#125;</span><br><span class="line">	...</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>这里也是做了一些缩减，把一些关键性的代码都列出来，都已经这么长了，我们只对<code>into(imageview)</code>做分析。</p>
<h2 id="步骤6：步骤5第32行"><a href="#步骤6：步骤5第32行" class="headerlink" title="步骤6：步骤5第32行"></a>步骤6：步骤5第32行</h2><p>我们直接跳过不重要的代码，看32行，调用了<code>into(...)</code>的重载方法，<code>into(glideContext.buildImageViewTarget(view, transcodeClass),/*targetListener=*/null,requestOptions);</code>其中传入的第一个参数<code>glideContext.buildImageViewTarget(view, transcodeClass)</code>是一个Target类型，我们首先来分析一下这个Target是什么</p>
<h2 id="步骤7：GlideContext-buildImageViewTarget"><a href="#步骤7：GlideContext-buildImageViewTarget" class="headerlink" title="步骤7：GlideContext#buildImageViewTarget()"></a>步骤7：GlideContext#buildImageViewTarget()</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@NonNull</span></span><br><span class="line"><span class="keyword">public</span> &lt;X&gt; <span class="function">ViewTarget&lt;ImageView, X&gt; <span class="title">buildImageViewTarget</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">    @NonNull ImageView imageView, @NonNull Class&lt;X&gt; transcodeClass)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> imageViewTargetFactory.buildTarget(imageView, transcodeClass);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>内部直接调用<code>imageViewTargetFactory.buildTarget()</code>，接着往下看</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">public &lt;Z&gt; ViewTarget&lt;ImageView, Z&gt; buildTarget(@NonNull ImageView view,</span><br><span class="line">                                                @NonNull Class&lt;Z&gt; clazz) &#123;</span><br><span class="line">    if (Bitmap.class.equals(clazz)) &#123;</span><br><span class="line">        return (ViewTarget&lt;ImageView, Z&gt;) new BitmapImageViewTarget(view);</span><br><span class="line">    &#125; else if (Drawable.class.isAssignableFrom(clazz)) &#123;</span><br><span class="line">        return (ViewTarget&lt;ImageView, Z&gt;) new DrawableImageViewTarget(view);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        throw new IllegalArgumentException(</span><br><span class="line">                &quot;Unhandled class: &quot; + clazz + &quot;, try .as*(Class).transcode(ResourceTranscoder)&quot;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这个方法很简单，判断了传入的clazz类型，那么这个clazz究竟是什么类型呢，回到步骤3中的第19行，</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public &lt;ResourceType&gt; RequestBuilder&lt;ResourceType&gt; as(@NonNull Class&lt;ResourceType&gt; 		resourceClass) &#123;</span><br><span class="line">    return new RequestBuilder&lt;&gt;(glide, this, resourceClass, context);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在as方法中，我们之前说过，as默认调用的是<code>as(Drawable.class)</code>，所以这里传入的clazz类型就是<code>Drawable</code>类型，那么显而易见这里<code>Target</code>指定为<code>DrawableImageViewTarget</code>类型。</p>
<h2 id="步骤8：步骤5第38行"><a href="#步骤8：步骤5第38行" class="headerlink" title="步骤8：步骤5第38行"></a>步骤8：步骤5第38行</h2><p>在步骤6中说过，<code>load()</code>方法调用了内部的重载<code>load()</code>方法，接着往下看，步骤5第48行代码，<code>Request request = buildRequest(target, targetListener, options);</code>构建了一个Request对象，跟进<code>buildRequest()</code>发现，步骤5第67行继续调用<code>buildRequestRecursive()</code>方法，再继续跟进从92行到101行，</p>
<p><code>Request mainRequest = buildThumbnailRequestRecursive(target, targetListener, parentCoordinator, transitionOptions, priority, overrideWidth, overrideHeight, requestOptions);</code></p>
<p>继续调用<code>buildThumbnailRequestRecursive()</code>，传入了一大堆参数，上面的<code>buildThumbnailRequestRecursive()</code>方法代码太多了，其实都是很清晰的逻辑，把它简化一下，如下所示</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">private Request buildRequestRecursive() &#123;</span><br><span class="line">    if (thumbnailBuilder != null) &#123;</span><br><span class="line">        ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);</span><br><span class="line">        Request fullRequest = obtainRequest(...);</span><br><span class="line">        Request thumbRequest = thumbnailBuilder.buildRequestRecursive(...);</span><br><span class="line">        coordinator.setRequests(fullRequest, thumbRequest);</span><br><span class="line">        return coordinator;</span><br><span class="line">    &#125; else if (thumbSizeMultiplier != null) &#123;</span><br><span class="line">        ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);</span><br><span class="line">        Request fullRequest = obtainRequest(...);</span><br><span class="line">        Request thumbRequest = thumbnailBuilder.buildRequestRecursive(...);</span><br><span class="line">        coordinator.setRequests(fullRequest, thumbRequest);</span><br><span class="line">        return coordinator;</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        return obtainRequest(...);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>首先判断thumbnailBuilder是否为null，其次判断thumbSizeMultiplier是否为null，其实他们两个都是null这里说明一下</p>
<blockquote>
<p>thumbnailBuilder会在Glide.with().load().thumbnail(builder).into()赋值</p>
<p>thumbSizeMultiplier会在Glide.with().load().thumbnail(float).into()进行赋值。</p>
</blockquote>
<p>最终走else代码<code>return obtainRequest(...);</code></p>
<p>在步骤5第228行，调用<code>SingleRequest.obtain()</code>方法</p>
<h2 id="步骤9：SingleRequest-obtain"><a href="#步骤9：SingleRequest-obtain" class="headerlink" title="步骤9：SingleRequest#obtain()"></a>步骤9：SingleRequest#obtain()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">public static &lt;R&gt; SingleRequest&lt;R&gt; obtain(</span><br><span class="line">        Context context,</span><br><span class="line">        GlideContext glideContext,</span><br><span class="line">        Object model,</span><br><span class="line">        Class&lt;R&gt; transcodeClass,</span><br><span class="line">        RequestOptions requestOptions,</span><br><span class="line">        int overrideWidth,</span><br><span class="line">        int overrideHeight,</span><br><span class="line">        Priority priority,</span><br><span class="line">        Target&lt;R&gt; target,</span><br><span class="line">        RequestListener&lt;R&gt; targetListener,</span><br><span class="line">        @Nullable List&lt;RequestListener&lt;R&gt;&gt; requestListeners,</span><br><span class="line">        RequestCoordinator requestCoordinator,</span><br><span class="line">        Engine engine,</span><br><span class="line">        TransitionFactory&lt;? super R&gt; animationFactory) &#123;</span><br><span class="line">    @SuppressWarnings(&quot;unchecked&quot;) SingleRequest&lt;R&gt; request =</span><br><span class="line">            (SingleRequest&lt;R&gt;) POOL.acquire();</span><br><span class="line">    if (request == null) &#123;</span><br><span class="line">        request = new SingleRequest&lt;&gt;();</span><br><span class="line">    &#125;</span><br><span class="line">    request.init(</span><br><span class="line">            context,</span><br><span class="line">            glideContext,</span><br><span class="line">            model,</span><br><span class="line">            transcodeClass,</span><br><span class="line">            requestOptions,</span><br><span class="line">            overrideWidth,</span><br><span class="line">            overrideHeight,</span><br><span class="line">            priority,</span><br><span class="line">            target,</span><br><span class="line">            targetListener,</span><br><span class="line">            requestListeners,</span><br><span class="line">            requestCoordinator,</span><br><span class="line">            engine,</span><br><span class="line">            animationFactory);</span><br><span class="line">    return request;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>一堆代码，提取有用信息，第18行，<code>request == null</code>成立，<code>request = new SingleRequest&lt;&gt;();</code>首先确定了<code>request</code>类型是<code>SingleRequest</code>对象。第21行做了一些初始化的操作，这里先放一放等以后用到了再回来慢慢看。咱们接着走主要流程。</p>
<h2 id="步骤10：步骤5第60行"><a href="#步骤10：步骤5第60行" class="headerlink" title="步骤10：步骤5第60行"></a>步骤10：步骤5第60行</h2><p> 步骤5第60行，<code>requestManager.track(target, request);</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">void track(@NonNull Target&lt;?&gt; target, @NonNull Request request) &#123;</span><br><span class="line">    targetTracker.track(target);</span><br><span class="line">    requestTracker.runRequest(request);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第3行，<code>requestTracker.runRequest(request);</code>来看一下<code>RequestTracker#runRequest()</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">runRequest</span><span class="params">(@NonNull Request request)</span> </span>&#123;</span><br><span class="line">    requests.add(request);</span><br><span class="line">    <span class="keyword">if</span> (!isPaused) &#123;</span><br><span class="line">        request.begin();</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        request.clear();</span><br><span class="line">        <span class="keyword">if</span> (Log.isLoggable(TAG, Log.VERBOSE)) &#123;</span><br><span class="line">            Log.v(TAG, <span class="string">"Paused, delaying request"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        pendingRequests.add(request);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第4行，<code>request.begin();</code>在步骤9中最终得到的<code>Request</code>是<code>SingleRequest</code>，我们来到<code>SingleRequest</code>中查看<code>begin()</code>方法</p>
<h2 id="步骤11：SingleRequest-begin"><a href="#步骤11：SingleRequest-begin" class="headerlink" title="步骤11：SingleRequest#begin()"></a>步骤11：SingleRequest#begin()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">@Override</span><br><span class="line">public void begin() &#123;</span><br><span class="line">    assertNotCallingCallbacks();</span><br><span class="line">    stateVerifier.throwIfRecycled();</span><br><span class="line">    startTime = LogTime.getLogTime();</span><br><span class="line">    if (model == null) &#123;</span><br><span class="line">        if (Util.isValidDimensions(overrideWidth, overrideHeight)) &#123;</span><br><span class="line">            width = overrideWidth;</span><br><span class="line">            height = overrideHeight;</span><br><span class="line">        &#125;</span><br><span class="line">        int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;</span><br><span class="line">        onLoadFailed(new GlideException(&quot;Received null model&quot;), logLevel);</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line">    if (status == SingleRequest.Status.RUNNING) &#123;</span><br><span class="line">        throw new IllegalArgumentException(&quot;Cannot restart a running request&quot;);</span><br><span class="line">    &#125;</span><br><span class="line">    if (status == SingleRequest.Status.COMPLETE) &#123;</span><br><span class="line">        onResourceReady(resource, DataSource.MEMORY_CACHE);</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line">    status = SingleRequest.Status.WAITING_FOR_SIZE;</span><br><span class="line">    if (Util.isValidDimensions(overrideWidth, overrideHeight)) &#123;</span><br><span class="line">        onSizeReady(overrideWidth, overrideHeight);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        target.getSize(this);</span><br><span class="line">    &#125;</span><br><span class="line">    if ((status == SingleRequest.Status.RUNNING || status == SingleRequest.Status.WAITING_FOR_SIZE)</span><br><span class="line">            &amp;&amp; canNotifyStatusChanged()) &#123;</span><br><span class="line">        target.onLoadStarted(getPlaceholderDrawable());</span><br><span class="line">    &#125;</span><br><span class="line">    if (IS_VERBOSE_LOGGABLE) &#123;</span><br><span class="line">        logV(&quot;finished run method in &quot; + LogTime.getElapsedMillis(startTime));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>来看一下这段代码干了什么，</p>
<ol>
<li><p>第6行，<code>if (model == null) {..}</code>然后<code>loadFailed()</code>，这很显然不会走，实际上model也不会为null。因为这个model是在步骤9中第21行调用init()方法时候赋值的成员变量，最早追溯到步骤4的第9行代码</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">private RequestBuilder&lt;TranscodeType&gt; loadGeneric(@Nullable Object model) &#123;</span><br><span class="line">	this.model = model;</span><br><span class="line">	isModelSet = true;</span><br><span class="line">	return this;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>我们针对<code>load(String url)</code>这个方法进行分析时，这个model是实际上是url链接，也就是String.class。</p>
</li>
<li><p>第15行判断status的值，直接告诉大家结果<code>status = Status.PENDING</code>，依据呢？其实还是在步骤9第21行调用<code>init()</code>方法初始化的时候赋值的，这些细节就不带大家分析了。接下来第22行</p>
<p><code>status = SingleRequest.Status.WAITING_FOR_SIZE;</code></p>
<p>第23行，<code>Util.isValidDimensions(overrideWidth, overrideHeight)</code>这个是false，所以会直接走else分支<code>target.getSize(this)</code>，那么这个<code>target</code>是谁呢？步骤7给出了答案：<code>DrawableImageViewTarget</code></p>
</li>
</ol>
<h2 id="步骤12：DrawableImageViewTarget-getSize"><a href="#步骤12：DrawableImageViewTarget-getSize" class="headerlink" title="步骤12：DrawableImageViewTarget#getSize()"></a>步骤12：DrawableImageViewTarget#getSize()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">public class DrawableImageViewTarget extends ImageViewTarget&lt;Drawable&gt; &#123;</span><br><span class="line">    public DrawableImageViewTarget(ImageView view) &#123;</span><br><span class="line">        super(view);</span><br><span class="line">    &#125;</span><br><span class="line">    /**</span><br><span class="line">     * @deprecated Use &#123;@link #waitForLayout()&#125; instead.</span><br><span class="line">     */</span><br><span class="line">    // Public API.</span><br><span class="line">    @SuppressWarnings(&#123;&quot;unused&quot;, &quot;deprecation&quot;&#125;)</span><br><span class="line">    @Deprecated</span><br><span class="line">    public DrawableImageViewTarget(ImageView view, boolean waitForLayout) &#123;</span><br><span class="line">        super(view, waitForLayout);</span><br><span class="line">    &#125;</span><br><span class="line">    @Override</span><br><span class="line">    protected void setResource(@Nullable Drawable resource) &#123;</span><br><span class="line">        view.setImageDrawable(resource);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里并没有看到<code>getSize()</code>方法，那就去父类里面找，最终来到<code>ViewTarget#getSize()</code></p>
<h2 id="步骤13：ViewTarget-getSize"><a href="#步骤13：ViewTarget-getSize" class="headerlink" title="步骤13：ViewTarget#getSize()"></a>步骤13：ViewTarget#getSize()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">@CallSuper</span><br><span class="line">@Override</span><br><span class="line">public void getSize(@NonNull SizeReadyCallback cb) &#123;</span><br><span class="line">  sizeDeterminer.getSize(cb);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>SizeDeterminer#getSize(cb);</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">void getSize(@NonNull SizeReadyCallback cb) &#123;</span><br><span class="line">    int currentWidth = getTargetWidth();</span><br><span class="line">    int currentHeight = getTargetHeight();</span><br><span class="line">    if (isViewStateAndSizeValid(currentWidth, currentHeight)) &#123;</span><br><span class="line">        cb.onSizeReady(currentWidth, currentHeight);</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line">    if (!cbs.contains(cb)) &#123;</span><br><span class="line">        cbs.add(cb);</span><br><span class="line">    &#125;</span><br><span class="line">    if (layoutListener == null) &#123;</span><br><span class="line">        ViewTreeObserver observer = view.getViewTreeObserver();</span><br><span class="line">        layoutListener = new SizeDeterminerLayoutListener(this);</span><br><span class="line">        observer.addOnPreDrawListener(layoutListener);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">private boolean isViewStateAndSizeValid(int width, int height) &#123;</span><br><span class="line">  return isDimensionValid(width) &amp;&amp; isDimensionValid(height);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">private boolean isDimensionValid(int size) &#123;</span><br><span class="line">  return size &gt; 0 || size == SIZE_ORIGINAL;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第一段代码很简单，调用了<code>sizeDeterminer.getSize(cb);</code>接着看下方<code>sizeDeterminer#getSize(cb)</code>方法，第4行判断<code>isViewStateAndSizeValid(currentWidth, currentHeight)</code>，简单来说，就是判断ImageView的width，height是否有效。</p>
<blockquote>
<p>这里有个小细节，可看可不看，不影响具体流程</p>
</blockquote>
<ol>
<li><p>如果我们的最原始的<code>ImageView</code>的宽高属性是<code>wrap_content</code>或者是<code>match_parent</code>，那么第4行代码的判断结果会是false，因为目前<code>ImageView</code>还未计算出具体的宽和高的值。会继续执行14行代码，用来监听布局初始化后的结果，来看一下第13行的<code>SizeDeterminerLayoutListener</code>类</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">private static final class SizeDeterminerLayoutListener</span><br><span class="line">        implements ViewTreeObserver.OnPreDrawListener &#123;</span><br><span class="line">    private final WeakReference&lt;ViewTarget.SizeDeterminer&gt; sizeDeterminerRef;</span><br><span class="line">    SizeDeterminerLayoutListener(@NonNull ViewTarget.SizeDeterminer sizeDeterminer) &#123;</span><br><span class="line">        sizeDeterminerRef = new WeakReference&lt;&gt;(sizeDeterminer);</span><br><span class="line">    &#125;</span><br><span class="line">    @Override</span><br><span class="line">    public boolean onPreDraw() &#123;</span><br><span class="line">        if (Log.isLoggable(TAG, Log.VERBOSE)) &#123;</span><br><span class="line">            Log.v(TAG, &quot;OnGlobalLayoutListener called attachStateListener=&quot; + this);</span><br><span class="line">        &#125;</span><br><span class="line">        ViewTarget.SizeDeterminer sizeDeterminer = sizeDeterminerRef.get();</span><br><span class="line">        if (sizeDeterminer != null) &#123;</span><br><span class="line">            sizeDeterminer.checkCurrentDimens();</span><br><span class="line">        &#125;</span><br><span class="line">        return true;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>看第14行，布局加载的回调中，会再次调用<code>sizeDeterminer.checkCurrentDimens();</code>检查当前的宽高</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">@Synthetic</span><br><span class="line">void checkCurrentDimens() &#123;</span><br><span class="line">    if (cbs.isEmpty()) &#123;</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line">    int currentWidth = getTargetWidth();</span><br><span class="line">    int currentHeight = getTargetHeight();</span><br><span class="line">    if (!isViewStateAndSizeValid(currentWidth, currentHeight)) &#123;</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line">    notifyCbs(currentWidth, currentHeight);</span><br><span class="line">    clearCallbacksAndListener();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>再看第8行，判断宽高属性是否有效，很显然，经过布局加载，宽高已经有效了，第11行，<code>notifyCbs()</code>方法是用来回调<code>onSizeReady()</code>的，如下所示，回调<code>cb.onSizeReady(width, height);</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">private void notifyCbs(int width, int height) &#123;</span><br><span class="line">    for (SizeReadyCallback cb : new ArrayList&lt;&gt;(cbs)) &#123;</span><br><span class="line">        cb.onSizeReady(width, height);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里可以看出，与步骤13的第二个代码块<code>sizeDeterminer#getSize(cb)</code>方法中的第5行是一样的。</p>
</li>
<li><p>如果<code>ImageView</code>的宽高被指定了比如100dp这样具体的数值，第4行代码会判断为true，表示宽高属性有效，同样会回调步骤13的第二个代码块<code>sizeDeterminer#getSize(cb)</code>方法中的第5行<code>cb.onSizeReady(width, height);</code></p>
</li>
</ol>
<h2 id="步骤14：SingleRequest-onSizeReady-width-height"><a href="#步骤14：SingleRequest-onSizeReady-width-height" class="headerlink" title="步骤14：SingleRequest#onSizeReady(width, height);"></a>步骤14：SingleRequest#onSizeReady(width, height);</h2><p>继续步骤13，<code>cb.onSizeReady(width, height);</code>这个cb是我们的目标对象，继续回到步骤11第26行代码，这是我们一开始分析<code>ImageView</code>的size的地方，这个cb可以看到就是<code>SingleRequest</code>对象，接下来跟一下<code>onSizeReady()</code>方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">@Override</span><br><span class="line">public void onSizeReady(int width, int height) &#123;</span><br><span class="line">    stateVerifier.throwIfRecycled();</span><br><span class="line">    if (IS_VERBOSE_LOGGABLE) &#123;</span><br><span class="line">        logV(&quot;Got onSizeReady in &quot; + LogTime.getElapsedMillis(startTime));</span><br><span class="line">    &#125;</span><br><span class="line">    if (status != SingleRequest.Status.WAITING_FOR_SIZE) &#123;</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line">    status = SingleRequest.Status.RUNNING;</span><br><span class="line">    float sizeMultiplier = requestOptions.getSizeMultiplier();</span><br><span class="line">    this.width = maybeApplySizeMultiplier(width, sizeMultiplier);</span><br><span class="line">    this.height = maybeApplySizeMultiplier(height, sizeMultiplier);</span><br><span class="line">    if (IS_VERBOSE_LOGGABLE) &#123;</span><br><span class="line">        logV(&quot;finished setup for calling load in &quot; + LogTime.getElapsedMillis(startTime));</span><br><span class="line">    &#125;</span><br><span class="line">    loadStatus = engine.load(</span><br><span class="line">            glideContext,</span><br><span class="line">            model,</span><br><span class="line">            requestOptions.getSignature(),</span><br><span class="line">            this.width,</span><br><span class="line">            this.height,</span><br><span class="line">            requestOptions.getResourceClass(),</span><br><span class="line">            transcodeClass,</span><br><span class="line">            priority,</span><br><span class="line">            requestOptions.getDiskCacheStrategy(),</span><br><span class="line">            requestOptions.getTransformations(),</span><br><span class="line">            requestOptions.isTransformationRequired(),</span><br><span class="line">            requestOptions.isScaleOnlyOrNoTransform(),</span><br><span class="line">            requestOptions.getOptions(),</span><br><span class="line">            requestOptions.isMemoryCacheable(),</span><br><span class="line">            requestOptions.getUseUnlimitedSourceGeneratorsPool(),</span><br><span class="line">            requestOptions.getUseAnimationPool(),</span><br><span class="line">            requestOptions.getOnlyRetrieveFromCache(),</span><br><span class="line">            this);</span><br><span class="line">    if (status != SingleRequest.Status.RUNNING) &#123;</span><br><span class="line">        loadStatus = null;</span><br><span class="line">    &#125;</span><br><span class="line">    if (IS_VERBOSE_LOGGABLE) &#123;</span><br><span class="line">        logV(&quot;finished onSizeReady in &quot; + LogTime.getElapsedMillis(startTime));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>看一下主要逻辑，第17行，<code>loadStatus = engine.load(....);</code>这个方法里面传了一大堆参数，先不管这些参数作用是什么，接着往下看</p>
<h2 id="步骤15：Engine-load"><a href="#步骤15：Engine-load" class="headerlink" title="步骤15：Engine#load()"></a>步骤15：Engine#load()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></td><td class="code"><pre><span class="line">public &lt;R&gt; LoadStatus load(</span><br><span class="line">        GlideContext glideContext,</span><br><span class="line">        Object model,</span><br><span class="line">        Key signature,</span><br><span class="line">        int width,</span><br><span class="line">        int height,</span><br><span class="line">        Class&lt;?&gt; resourceClass,</span><br><span class="line">        Class&lt;R&gt; transcodeClass,</span><br><span class="line">        Priority priority,</span><br><span class="line">        DiskCacheStrategy diskCacheStrategy,</span><br><span class="line">        Map&lt;Class&lt;?&gt;, Transformation&lt;?&gt;&gt; transformations,</span><br><span class="line">        boolean isTransformationRequired,</span><br><span class="line">        boolean isScaleOnlyOrNoTransform,</span><br><span class="line">        Options options,</span><br><span class="line">        boolean isMemoryCacheable,</span><br><span class="line">        boolean useUnlimitedSourceExecutorPool,</span><br><span class="line">        boolean useAnimationPool,</span><br><span class="line">        boolean onlyRetrieveFromCache,</span><br><span class="line">        ResourceCallback cb) &#123;</span><br><span class="line">    Util.assertMainThread();</span><br><span class="line">    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;</span><br><span class="line">    EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,</span><br><span class="line">            resourceClass, transcodeClass, options);</span><br><span class="line">    EngineResource&lt;?&gt; active = loadFromActiveResources(key, isMemoryCacheable);</span><br><span class="line">    if (active != null) &#123;</span><br><span class="line">        cb.onResourceReady(active, DataSource.MEMORY_CACHE);</span><br><span class="line">        if (VERBOSE_IS_LOGGABLE) &#123;</span><br><span class="line">            logWithTimeAndKey(&quot;Loaded resource from active resources&quot;, startTime, key);</span><br><span class="line">        &#125;</span><br><span class="line">        return null;</span><br><span class="line">    &#125;</span><br><span class="line">    EngineResource&lt;?&gt; cached = loadFromCache(key, isMemoryCacheable);</span><br><span class="line">    if (cached != null) &#123;</span><br><span class="line">        cb.onResourceReady(cached, DataSource.MEMORY_CACHE);</span><br><span class="line">        if (VERBOSE_IS_LOGGABLE) &#123;</span><br><span class="line">            logWithTimeAndKey(&quot;Loaded resource from cache&quot;, startTime, key);</span><br><span class="line">        &#125;</span><br><span class="line">        return null;</span><br><span class="line">    &#125;</span><br><span class="line">    EngineJob&lt;?&gt; current = jobs.get(key, onlyRetrieveFromCache);</span><br><span class="line">    if (current != null) &#123;</span><br><span class="line">        current.addCallback(cb);</span><br><span class="line">        if (VERBOSE_IS_LOGGABLE) &#123;</span><br><span class="line">            logWithTimeAndKey(&quot;Added to existing load&quot;, startTime, key);</span><br><span class="line">        &#125;</span><br><span class="line">        return new LoadStatus(cb, current);</span><br><span class="line">    &#125;</span><br><span class="line">    EngineJob&lt;R&gt; engineJob =</span><br><span class="line">            engineJobFactory.build(</span><br><span class="line">                    key,</span><br><span class="line">                    isMemoryCacheable,</span><br><span class="line">                    useUnlimitedSourceExecutorPool,</span><br><span class="line">                    useAnimationPool,</span><br><span class="line">                    onlyRetrieveFromCache);</span><br><span class="line">    DecodeJob&lt;R&gt; decodeJob =</span><br><span class="line">            decodeJobFactory.build(</span><br><span class="line">                    glideContext,</span><br><span class="line">                    model,</span><br><span class="line">                    key,</span><br><span class="line">                    signature,</span><br><span class="line">                    width,</span><br><span class="line">                    height,</span><br><span class="line">                    resourceClass,</span><br><span class="line">                    transcodeClass,</span><br><span class="line">                    priority,</span><br><span class="line">                    diskCacheStrategy,</span><br><span class="line">                    transformations,</span><br><span class="line">                    isTransformationRequired,</span><br><span class="line">                    isScaleOnlyOrNoTransform,</span><br><span class="line">                    onlyRetrieveFromCache,</span><br><span class="line">                    options,</span><br><span class="line">                    engineJob);</span><br><span class="line"></span><br><span class="line">    jobs.put(key, engineJob);</span><br><span class="line">    engineJob.addCallback(cb);</span><br><span class="line">    engineJob.start(decodeJob);</span><br><span class="line">    if (VERBOSE_IS_LOGGABLE) &#123;</span><br><span class="line">        logWithTimeAndKey(&quot;Started new load&quot;, startTime, key);</span><br><span class="line">    &#125;</span><br><span class="line">    return new LoadStatus(cb, engineJob);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上方代码块直接从第48行开始看，48行之前基本都是关于缓存的处理，而且，从这一步骤开始，才是真正的图片处理的逻辑。从第48和49行得到一个<code>EngineJob</code>对象，第55和56行得到一个<code>DecodeJob</code>对象，这两个对象与接下来的逻辑处理息息相关。接着看第76行，<code>engineJob.start(decodeJob);</code>看一下这个start()方法做了什么</p>
<h2 id="步骤16：EngineJob-start"><a href="#步骤16：EngineJob-start" class="headerlink" title="步骤16：EngineJob#start()"></a>步骤16：EngineJob#start()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">public void start(DecodeJob&lt;R&gt; decodeJob) &#123;</span><br><span class="line">    this.decodeJob = decodeJob;</span><br><span class="line">    GlideExecutor executor = decodeJob.willDecodeFromCache()</span><br><span class="line">            ? diskCacheExecutor</span><br><span class="line">            : getActiveSourceExecutor();</span><br><span class="line">    executor.execute(decodeJob);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>比较简单的代码，在第6行<code>executor.execute(decodeJob);</code>在一个线程池中开启线程，这个线程对象就是传入的<code>decodeJob</code>，可见接下来的代码都会在子线程运行，既然<code>DecodeJob</code>是一个线程对象，我们直接来找<code>DecodeJob#run()</code>方法就行了</p>
<h2 id="步骤17：DecodeJob-run"><a href="#步骤17：DecodeJob-run" class="headerlink" title="步骤17：DecodeJob#run()"></a>步骤17：DecodeJob#run()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">@Override</span><br><span class="line">public void run() &#123;</span><br><span class="line">    GlideTrace.beginSectionFormat(&quot;DecodeJob#run(model=%s)&quot;, model);</span><br><span class="line">    DataFetcher&lt;?&gt; localFetcher = currentFetcher;</span><br><span class="line">    try &#123;</span><br><span class="line">        if (isCancelled) &#123;</span><br><span class="line">            notifyFailed();</span><br><span class="line">            return;</span><br><span class="line">        &#125;</span><br><span class="line">        runWrapped();</span><br><span class="line">    &#125; catch (Throwable t) &#123;</span><br><span class="line">        if (Log.isLoggable(TAG, Log.DEBUG)) &#123;</span><br><span class="line">            Log.d(TAG, &quot;DecodeJob threw unexpectedly&quot;</span><br><span class="line">                    + &quot;, isCancelled: &quot; + isCancelled</span><br><span class="line">                    + &quot;, stage: &quot; + stage, t);</span><br><span class="line">        &#125;</span><br><span class="line">        if (stage != Stage.ENCODE) &#123;</span><br><span class="line">            throwables.add(t);</span><br><span class="line">            notifyFailed();</span><br><span class="line">        &#125;</span><br><span class="line">        if (!isCancelled) &#123;</span><br><span class="line">            throw t;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; finally &#123;</span><br><span class="line">        if (localFetcher != null) &#123;</span><br><span class="line">            localFetcher.cleanup();</span><br><span class="line">        &#125;</span><br><span class="line">        GlideTrace.endSection();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>我直接去掉了源码中的注释，比较清晰了。<code>run()</code>方法比较简单，就是继续执行了第10行，<code>runWrapped()</code>方法</p>
<h2 id="步骤18：DecodeJob-runWrapped"><a href="#步骤18：DecodeJob-runWrapped" class="headerlink" title="步骤18：DecodeJob#runWrapped()"></a>步骤18：DecodeJob#runWrapped()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">private void runWrapped() &#123;</span><br><span class="line">    switch (runReason) &#123;</span><br><span class="line">        case INITIALIZE:</span><br><span class="line">            stage = getNextStage(Stage.INITIALIZE);</span><br><span class="line">            currentGenerator = getNextGenerator();</span><br><span class="line">            runGenerators();</span><br><span class="line">            break;</span><br><span class="line">        case SWITCH_TO_SOURCE_SERVICE:</span><br><span class="line">            runGenerators();</span><br><span class="line">            break;</span><br><span class="line">        case DECODE_DATA:</span><br><span class="line">            decodeFromRetrievedData();</span><br><span class="line">            break;</span><br><span class="line">        default:</span><br><span class="line">            throw new IllegalStateException(&quot;Unrecognized run reason: &quot; + runReason);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上方代码需要判断<code>runReason</code>的状态，这里回到步骤15的56行可以看到<code>DecodeJob</code>对象是通过<code>DecodeJobFactory#build()</code>方法创建的，这个<code>DecodeJobFactory</code>对象是<code>Engine</code>类的内部类，在<code>DecodeJobFactory#build()</code>方法中又继续调用了<code>DecodeJob#init()</code>方法，在<code>init()</code>方法中可以知道<code>runReason = RunReason.INITIALIZE；</code>具体代码就不贴了。接着走到第4行代码，<code>stage = getNextStage(Stage.INITIALIZE)；</code>为成员变量stage赋值，继续来看<code>getNextStage()</code>方法</p>
<h2 id="步骤19：DecodeJob-getNextStage"><a href="#步骤19：DecodeJob-getNextStage" class="headerlink" title="步骤19：DecodeJob#getNextStage()"></a>步骤19：DecodeJob#getNextStage()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">private Stage getNextStage(Stage current) &#123;</span><br><span class="line">    switch (current) &#123;</span><br><span class="line">        case INITIALIZE:</span><br><span class="line">            return diskCacheStrategy.decodeCachedResource()</span><br><span class="line">                    ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);</span><br><span class="line">        case RESOURCE_CACHE:</span><br><span class="line">            return diskCacheStrategy.decodeCachedData()</span><br><span class="line">                    ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);</span><br><span class="line">        case DATA_CACHE:</span><br><span class="line">            // Skip loading from source if the user opted to only retrieve the resource from cache.</span><br><span class="line">            return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;</span><br><span class="line">        case SOURCE:</span><br><span class="line">        case FINISHED:</span><br><span class="line">            return Stage.FINISHED;</span><br><span class="line">        default:</span><br><span class="line">            throw new IllegalArgumentException(&quot;Unrecognized stage: &quot; + current);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>走<code>INITIALIZE</code>分支，看第4行代码<code>return diskCacheStrategy.decodeCachedResource() ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);</code>首先要知道这个三元运算符的结果，来看一下这个<code>diskCacheStrategy</code>是什么时候赋值的，这里不贴代码了，其实我们只需要看步骤14中的第26行<code>requestOptions.getDiskCacheStrategy()</code>知道是通过<code>requestOptions</code>拿到的，这个<code>RequestOptions</code>我们现在是没有用到的，他是用来指定Glide的其它条件的，由于我们这里就是最简单的加载步骤，那么这里赋值的是默认值<code>diskCacheStrategy = DiskCacheStrategy.AUTOMATIC</code></p>
<h2 id="步骤20：DiskCacheStrategy-AUTOMATIC"><a href="#步骤20：DiskCacheStrategy-AUTOMATIC" class="headerlink" title="步骤20：DiskCacheStrategy#AUTOMATIC"></a>步骤20：DiskCacheStrategy#AUTOMATIC</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">public static final DiskCacheStrategy AUTOMATIC = new DiskCacheStrategy() &#123;</span><br><span class="line">    @Override</span><br><span class="line">    public boolean isDataCacheable(DataSource dataSource) &#123;</span><br><span class="line">        return dataSource == DataSource.REMOTE;</span><br><span class="line">    &#125;</span><br><span class="line">    @Override</span><br><span class="line">    public boolean isResourceCacheable(boolean isFromAlternateCacheKey, DataSource dataSource,</span><br><span class="line">                                       EncodeStrategy encodeStrategy) &#123;</span><br><span class="line">        return ((isFromAlternateCacheKey &amp;&amp; dataSource == DataSource.DATA_DISK_CACHE)</span><br><span class="line">                || dataSource == DataSource.LOCAL)</span><br><span class="line">                &amp;&amp; encodeStrategy == EncodeStrategy.TRANSFORMED;</span><br><span class="line">    &#125;</span><br><span class="line">    @Override</span><br><span class="line">    public boolean decodeCachedResource() &#123;</span><br><span class="line">        return true;</span><br><span class="line">    &#125;</span><br><span class="line">    @Override</span><br><span class="line">    public boolean decodeCachedData() &#123;</span><br><span class="line">        return true;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<p>大家都知道，Glide是可以自己选择缓存策略的，如果我们没有选择缓存策略，Glide默认选中的就是这个已经实现的<code>AUTOMATIC</code>内部类，其它可供选择的还有<code>ALL，NONE，DATA，RESOURCE</code>，我们针对这个<code>AUTOMATIC</code>做分析，首先看步骤19提到的<code>decodeCachedResource()</code>方法，第15行，<code>return true;</code>回到步骤19，<code>getNextStage()</code>方法有了结果，<code>Stage.RESOURCE_CACHE</code>，那么步骤18也就有了结果，<code>stage = Stage.RESOURCE_CACHE</code>;接着运行步骤18第5行代码<code>getNextGenerator()</code></p>
<h2 id="步骤21：DecodeJob-getNextGenerator"><a href="#步骤21：DecodeJob-getNextGenerator" class="headerlink" title="步骤21：DecodeJob#getNextGenerator()"></a>步骤21：DecodeJob#getNextGenerator()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">private DataFetcherGenerator getNextGenerator() &#123;</span><br><span class="line">    switch (stage) &#123;</span><br><span class="line">        case RESOURCE_CACHE:</span><br><span class="line">            return new ResourceCacheGenerator(decodeHelper, this);</span><br><span class="line">        case DATA_CACHE:</span><br><span class="line">            return new DataCacheGenerator(decodeHelper, this);</span><br><span class="line">        case SOURCE:</span><br><span class="line">            return new SourceGenerator(decodeHelper, this);</span><br><span class="line">        case FINISHED:</span><br><span class="line">            return null;</span><br><span class="line">        default:</span><br><span class="line">            throw new IllegalStateException(&quot;Unrecognized stage: &quot; + stage);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>首先判断了<code>stage</code>状态，步骤20已经得到结果了<code>stage = Stage.RESOURCE_CACHE</code>，那么<code>return new ResourceCacheGenerator(decodeHelper, this)</code>，再回到步骤18，<code>currentGenerator = new ResourceCacheGenerator(decodeHelper, this)</code>；接着步骤18第6行，<code>runGenerators();</code></p>
<blockquote>
<p>理论上，从名称来看，我们首次执行加载流程直接看第8行，SourceGenerator就可以了，其他两个Generator也确实是得不到想要的结果，但是实际上在ResourceCacheGenerator做了一些初始化配置的工作，并把这些配置缓存了下来，我们就接着往下看</p>
</blockquote>
<h2 id="步骤22：DecodeJob-runGenerators"><a href="#步骤22：DecodeJob-runGenerators" class="headerlink" title="步骤22：DecodeJob#runGenerators()"></a>步骤22：DecodeJob#runGenerators()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">private void runGenerators() &#123;</span><br><span class="line">    currentThread = Thread.currentThread();</span><br><span class="line">    startFetchTime = LogTime.getLogTime();</span><br><span class="line">    boolean isStarted = false;</span><br><span class="line">    while (!isCancelled &amp;&amp; currentGenerator != null</span><br><span class="line">            &amp;&amp; !(isStarted = currentGenerator.startNext())) &#123;</span><br><span class="line">        stage = getNextStage(stage);</span><br><span class="line">        currentGenerator = getNextGenerator();</span><br><span class="line">        if (stage == Stage.SOURCE) &#123;</span><br><span class="line">            reschedule();</span><br><span class="line">            return;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    if ((stage == Stage.FINISHED || isCancelled) &amp;&amp; !isStarted) &#123;</span><br><span class="line">        notifyFailed();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>来到第5行进行判断，<code>isCancelled</code>和<code>currentGenerator</code>这两个都满足条件，第6行的<code>isStarted</code>才刚刚在第4行被赋值为false，这里关键就是看第6行的<code>currentGenerator.startNext()</code>运行结果，在步骤21中指定了<code>currentGenerator = ResourceCacheGenerator()</code>，那我们接往下看</p>
<h2 id="步骤23：ResourceCacheGenerator-startNext"><a href="#步骤23：ResourceCacheGenerator-startNext" class="headerlink" title="步骤23：ResourceCacheGenerator#startNext()"></a>步骤23：ResourceCacheGenerator#startNext()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line">public boolean startNext() &#123;</span><br><span class="line">    List&lt;Key&gt; sourceIds = helper.getCacheKeys();</span><br><span class="line">    if (sourceIds.isEmpty()) &#123;</span><br><span class="line">        return false;</span><br><span class="line">    &#125;</span><br><span class="line">    List&lt;Class&lt;?&gt;&gt; resourceClasses = helper.getRegisteredResourceClasses();</span><br><span class="line">    if (resourceClasses.isEmpty()) &#123;</span><br><span class="line">        if (File.class.equals(helper.getTranscodeClass())) &#123;</span><br><span class="line">            return false;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    while (modelLoaders == null || !hasNextModelLoader()) &#123;</span><br><span class="line">        resourceClassIndex++;</span><br><span class="line">        if (resourceClassIndex &gt;= resourceClasses.size()) &#123;</span><br><span class="line">            sourceIdIndex++;</span><br><span class="line">            if (sourceIdIndex &gt;= sourceIds.size()) &#123;</span><br><span class="line">                return false;</span><br><span class="line">            &#125;</span><br><span class="line">            resourceClassIndex = 0;</span><br><span class="line">        &#125;</span><br><span class="line">        Key sourceId = sourceIds.get(sourceIdIndex);</span><br><span class="line">        Class&lt;?&gt; resourceClass = resourceClasses.get(resourceClassIndex);</span><br><span class="line">        Transformation&lt;?&gt; transformation = helper.getTransformation(resourceClass);</span><br><span class="line">        currentKey =</span><br><span class="line">                new ResourceCacheKey(// NOPMD AvoidInstantiatingObjectsInLoops</span><br><span class="line">                        helper.getArrayPool(),</span><br><span class="line">                        sourceId,</span><br><span class="line">                        helper.getSignature(),</span><br><span class="line">                        helper.getWidth(),</span><br><span class="line">                        helper.getHeight(),</span><br><span class="line">                        transformation,</span><br><span class="line">                        resourceClass,</span><br><span class="line">                        helper.getOptions());</span><br><span class="line">        cacheFile = helper.getDiskCache().get(currentKey);</span><br><span class="line">        if (cacheFile != null) &#123;</span><br><span class="line">            sourceKey = sourceId;</span><br><span class="line">            modelLoaders = helper.getModelLoaders(cacheFile);</span><br><span class="line">            modelLoaderIndex = 0;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    loadData = null;</span><br><span class="line">    boolean started = false;</span><br><span class="line">    while (!started &amp;&amp; hasNextModelLoader()) &#123;</span><br><span class="line">        ModelLoader&lt;File, ?&gt; modelLoader = modelLoaders.get(modelLoaderIndex++);</span><br><span class="line">        loadData = modelLoader.buildLoadData(cacheFile,</span><br><span class="line">                helper.getWidth(), helper.getHeight(), helper.getOptions());</span><br><span class="line">        if (loadData != null &amp;&amp; helper.hasLoadPath(loadData.fetcher.getDataClass())) &#123;</span><br><span class="line">            started = true;</span><br><span class="line">            loadData.fetcher.loadData(helper.getPriority(), this);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return started;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>看一下关键步骤第2行，<code>helper.getCacheKeys()</code>，接下来会有一些其他类的方法，分析完内部逻辑之后，我们再回到这个步骤</p>
<h2 id="步骤24：DecodeHelper-getCacheKeys"><a href="#步骤24：DecodeHelper-getCacheKeys" class="headerlink" title="步骤24：DecodeHelper#getCacheKeys()"></a>步骤24：DecodeHelper#getCacheKeys()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">List&lt;Key&gt; getCacheKeys() &#123;</span><br><span class="line">    if (!isCacheKeysSet) &#123;</span><br><span class="line">        isCacheKeysSet = true;</span><br><span class="line">        cacheKeys.clear();</span><br><span class="line">        List&lt;LoadData&lt;?&gt;&gt; loadData = getLoadData();</span><br><span class="line">        for (int i = 0, size = loadData.size(); i &lt; size; i++) &#123;</span><br><span class="line">            LoadData&lt;?&gt; data = loadData.get(i);</span><br><span class="line">            if (!cacheKeys.contains(data.sourceKey)) &#123;</span><br><span class="line">                cacheKeys.add(data.sourceKey);</span><br><span class="line">            &#125;</span><br><span class="line">            for (int j = 0; j &lt; data.alternateKeys.size(); j++) &#123;</span><br><span class="line">                if (!cacheKeys.contains(data.alternateKeys.get(j))) &#123;</span><br><span class="line">                    cacheKeys.add(data.alternateKeys.get(j));</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return cacheKeys;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第5行，<code>getLoadData()</code>，继续往下走</p>
<h2 id="步骤25：DecodeHelper-getLoadData"><a href="#步骤25：DecodeHelper-getLoadData" class="headerlink" title="步骤25：DecodeHelper#getLoadData()"></a>步骤25：DecodeHelper#getLoadData()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">List&lt;LoadData&lt;?&gt;&gt; getLoadData() &#123;</span><br><span class="line">    if (!isLoadDataSet) &#123;</span><br><span class="line">        isLoadDataSet = true;</span><br><span class="line">        loadData.clear();</span><br><span class="line">        List&lt;ModelLoader&lt;Object, ?&gt;&gt; modelLoaders = glideContext.getRegistry().getModelLoaders(model);</span><br><span class="line">        //noinspection ForLoopReplaceableByForEach to improve perf</span><br><span class="line">        for (int i = 0, size = modelLoaders.size(); i &lt; size; i++) &#123;</span><br><span class="line">            ModelLoader&lt;Object, ?&gt; modelLoader = modelLoaders.get(i);</span><br><span class="line">            LoadData&lt;?&gt; current =</span><br><span class="line">                    modelLoader.buildLoadData(model, width, height, options);</span><br><span class="line">            if (current != null) &#123;</span><br><span class="line">                loadData.add(current);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return loadData;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第1行，<code>isLoadDataSet</code>初始化为false，尚未初始化<code>loadData</code>集合，接着第5行，<code>glideContext.getRegistry().getModelLoaders(model)</code>，不用考虑这个<code>glideContext</code>对象和<code>getRegistry()</code>方法返回的<code>Registry</code>对象是什么时候初始化的，直接看<code>Registry#getModelLoaders()</code>方法</p>
<h2 id="步骤26：Registry-getModelLoaders"><a href="#步骤26：Registry-getModelLoaders" class="headerlink" title="步骤26：Registry#getModelLoaders()"></a>步骤26：Registry#getModelLoaders()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">@NonNull</span><br><span class="line">public &lt;Model&gt; List&lt;ModelLoader&lt;Model, ?&gt;&gt; getModelLoaders(@NonNull Model model) &#123;</span><br><span class="line">    List&lt;ModelLoader&lt;Model, ?&gt;&gt; result = modelLoaderRegistry.getModelLoaders(model);</span><br><span class="line">    if (result.isEmpty()) &#123;</span><br><span class="line">        throw new NoModelLoaderAvailableException(model);</span><br><span class="line">    &#125;</span><br><span class="line">    return result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>看第3行就知道，又要继续跳转代码了， <code>modelLoaderRegistry.getModelLoaders(model);</code></p>
<h2 id="步骤27：ModelLoaderRegistry-getModelLoaders"><a href="#步骤27：ModelLoaderRegistry-getModelLoaders" class="headerlink" title="步骤27：ModelLoaderRegistry#getModelLoaders()"></a>步骤27：ModelLoaderRegistry#getModelLoaders()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">public &lt;A&gt; List&lt;ModelLoader&lt;A, ?&gt;&gt; getModelLoaders(@NonNull A model) &#123;</span><br><span class="line">    List&lt;ModelLoader&lt;A, ?&gt;&gt; modelLoaders = getModelLoadersForClass(getClass(model));</span><br><span class="line">    int size = modelLoaders.size();</span><br><span class="line">    boolean isEmpty = true;</span><br><span class="line">    List&lt;ModelLoader&lt;A, ?&gt;&gt; filteredLoaders = Collections.emptyList();</span><br><span class="line">    //noinspection ForLoopReplaceableByForEach to improve perf</span><br><span class="line">    for (int i = 0; i &lt; size; i++) &#123;</span><br><span class="line">        ModelLoader&lt;A, ?&gt; loader = modelLoaders.get(i);</span><br><span class="line">        if (loader.handles(model)) &#123;</span><br><span class="line">            if (isEmpty) &#123;</span><br><span class="line">                filteredLoaders = new ArrayList&lt;&gt;(size - i);</span><br><span class="line">                isEmpty = false;</span><br><span class="line">            &#125;</span><br><span class="line">            filteredLoaders.add(loader);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return filteredLoaders;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>还没有结束，看到第2行<code>getModelLoadersForClass(getClass(model))</code>，接着往下</p>
<h2 id="步骤28：ModelLoaderRegistry-getModelLoadersForClass"><a href="#步骤28：ModelLoaderRegistry-getModelLoadersForClass" class="headerlink" title="步骤28：ModelLoaderRegistry#getModelLoadersForClass()"></a>步骤28：ModelLoaderRegistry#getModelLoadersForClass()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">private synchronized &lt;A&gt; List&lt;ModelLoader&lt;A, ?&gt;&gt; getModelLoadersForClass(</span><br><span class="line">        @NonNull Class&lt;A&gt; modelClass) &#123;</span><br><span class="line">    List&lt;ModelLoader&lt;A, ?&gt;&gt; loaders = cache.get(modelClass);</span><br><span class="line">    if (loaders == null) &#123;</span><br><span class="line">        loaders = Collections.unmodifiableList(multiModelLoaderFactory.build(modelClass));</span><br><span class="line">        cache.put(modelClass, loaders);</span><br><span class="line">    &#125;</span><br><span class="line">    return loaders;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>看着似乎快要走到底了，我们来看一下第3行，<code>cache.get(modelClass);</code>这里的<code>cache</code>是用来做缓存的，我们可以把他当成集合来看待。第3行执行完毕，第4行判断<code>loaders</code>是否为null，很显然这里是null，因为我们之前的步骤没有做过这个初始化，接着第5行，<code>multiModelLoaderFactory.build(modelClass)</code>这个方法可以对<code>loaders</code>赋值</p>
<h2 id="步骤29：MultiModelLoaderFactory-build"><a href="#步骤29：MultiModelLoaderFactory-build" class="headerlink" title="步骤29：MultiModelLoaderFactory#build()"></a>步骤29：MultiModelLoaderFactory#build()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">@NonNull</span><br><span class="line">synchronized &lt;Model&gt; List&lt;ModelLoader&lt;Model, ?&gt;&gt; build(@NonNull Class&lt;Model&gt; modelClass) &#123;</span><br><span class="line">    try &#123;</span><br><span class="line">        List&lt;ModelLoader&lt;Model, ?&gt;&gt; loaders = new ArrayList&lt;&gt;();</span><br><span class="line">        for (Entry&lt;?, ?&gt; entry : entries) &#123;</span><br><span class="line">            if (alreadyUsedEntries.contains(entry)) &#123;</span><br><span class="line">                continue;</span><br><span class="line">            &#125;</span><br><span class="line">            if (entry.handles(modelClass)) &#123;</span><br><span class="line">                alreadyUsedEntries.add(entry);</span><br><span class="line">                loaders.add(this.&lt;Model, Object&gt;build(entry));</span><br><span class="line">                alreadyUsedEntries.remove(entry);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        return loaders;</span><br><span class="line">    &#125; catch (Throwable t) &#123;</span><br><span class="line">        alreadyUsedEntries.clear();</span><br><span class="line">        throw t;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>又是一个新的类，第5行，直接对<code>entries</code>进行遍历，这个<code>entries</code>我们需要搞清楚是什么，在<code>MultiModelLoaderFactory</code>中看到了其实就是一个Entry集合，这个<code>Entry</code>类到下面可以简单看一下是什么</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">private final List&lt;Entry&lt;?, ?&gt;&gt; entries = new ArrayList&lt;&gt;();</span><br></pre></td></tr></table></figure>
<p>在这个类中搜索了一下发现他是在这里初始化的</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">private &lt;Model, Data&gt; void add(</span><br><span class="line">        @NonNull Class&lt;Model&gt; modelClass,</span><br><span class="line">        @NonNull Class&lt;Data&gt; dataClass,</span><br><span class="line">        @NonNull ModelLoaderFactory&lt;? extends Model, ? extends Data&gt; factory,</span><br><span class="line">        boolean append) &#123;</span><br><span class="line">    Entry&lt;Model, Data&gt; entry = new Entry&lt;&gt;(modelClass, dataClass, factory);</span><br><span class="line">    entries.add(append ? entries.size() : 0, entry);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第6行，把<code>add()</code>方法传入的参数放在<code>Entry</code>中封装成了一个对象，在第7行里看到了<code>add()</code>方法，我们现在需要找到是谁调用了这个<code>MultiModelLoaderFactory#add()</code>方法</p>
<h2 id="步骤30：MultiModelLoaderFactory-append"><a href="#步骤30：MultiModelLoaderFactory-append" class="headerlink" title="步骤30：MultiModelLoaderFactory#append()"></a>步骤30：MultiModelLoaderFactory#append()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">synchronized &lt;Model, Data&gt; void append(</span><br><span class="line">        @NonNull Class&lt;Model&gt; modelClass,</span><br><span class="line">        @NonNull Class&lt;Data&gt; dataClass,</span><br><span class="line">        @NonNull ModelLoaderFactory&lt;? extends Model, ? extends Data&gt; factory) &#123;</span><br><span class="line">    add(modelClass, dataClass, factory, /*append=*/ true);</span><br><span class="line">&#125;</span><br><span class="line">synchronized &lt;Model, Data&gt; void prepend(</span><br><span class="line">        @NonNull Class&lt;Model&gt; modelClass,</span><br><span class="line">        @NonNull Class&lt;Data&gt; dataClass,</span><br><span class="line">        @NonNull ModelLoaderFactory&lt;? extends Model, ? extends Data&gt; factory) &#123;</span><br><span class="line">    add(modelClass, dataClass, factory, /*append=*/ false);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>还是在这个类里面发现了这两个方法调用了<code>add()</code>方法，看逻辑就知道，<code>append()</code>方法是用来在集合末尾处添加，<code>prepend()</code>则是在集合最前面加入，我们在两个方法中随便挑一个找一下调用处就可以了，就看<code>append()</code>方法吧。</p>
<h2 id="步骤31：ModelLoaderRegistry-append"><a href="#步骤31：ModelLoaderRegistry-append" class="headerlink" title="步骤31：ModelLoaderRegistry#append()"></a>步骤31：ModelLoaderRegistry#append()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">public synchronized &lt;Model, Data&gt; void append(</span><br><span class="line">        @NonNull Class&lt;Model&gt; modelClass,</span><br><span class="line">        @NonNull Class&lt;Data&gt; dataClass,</span><br><span class="line">        @NonNull ModelLoaderFactory&lt;? extends Model, ? extends Data&gt; factory) &#123;</span><br><span class="line">    multiModelLoaderFactory.append(modelClass, dataClass, factory);</span><br><span class="line">    cache.clear();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第5行，原来是<code>ModelLoaderRegistry#append()</code>方法调用了<code>MultiModelLoaderFactory#append()</code>方法，这里还不是终点，继续往上找调用处</p>
<h2 id="步骤32：Registry-append"><a href="#步骤32：Registry-append" class="headerlink" title="步骤32：Registry#append()"></a>步骤32：Registry#append()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@NonNull</span><br><span class="line">public &lt;Model, Data&gt; Registry append(</span><br><span class="line">        @NonNull Class&lt;Model&gt; modelClass, @NonNull Class&lt;Data&gt; dataClass,</span><br><span class="line">        @NonNull ModelLoaderFactory&lt;Model, Data&gt; factory) &#123;</span><br><span class="line">    modelLoaderRegistry.append(modelClass, dataClass, factory);</span><br><span class="line">    return this;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>发现这里依旧不是终点</p>
<h2 id="步骤33：Glide-…"><a href="#步骤33：Glide-…" class="headerlink" title="步骤33：Glide(…)"></a>步骤33：Glide(…)</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">Glide(</span><br><span class="line">        @NonNull Context context,</span><br><span class="line">        @NonNull Engine engine,</span><br><span class="line">        @NonNull MemoryCache memoryCache,</span><br><span class="line">        @NonNull BitmapPool bitmapPool,</span><br><span class="line">        @NonNull ArrayPool arrayPool,</span><br><span class="line">        @NonNull RequestManagerRetriever requestManagerRetriever,</span><br><span class="line">        @NonNull ConnectivityMonitorFactory connectivityMonitorFactory,</span><br><span class="line">        int logLevel,</span><br><span class="line">        @NonNull RequestOptions defaultRequestOptions,</span><br><span class="line">        @NonNull Map&lt;Class&lt;?&gt;, TransitionOptions&lt;?, ?&gt;&gt; defaultTransitionOptions) &#123;</span><br><span class="line">    this.engine = engine;</span><br><span class="line">    this.bitmapPool = bitmapPool;</span><br><span class="line">    this.arrayPool = arrayPool;</span><br><span class="line">    this.memoryCache = memoryCache;</span><br><span class="line">    this.requestManagerRetriever = requestManagerRetriever;</span><br><span class="line">    this.connectivityMonitorFactory = connectivityMonitorFactory;</span><br><span class="line">    //此处省略若干代码......</span><br><span class="line">    registry = new Registry();</span><br><span class="line">    BitmapBytesTranscoder bitmapBytesTranscoder = new BitmapBytesTranscoder();</span><br><span class="line">    GifDrawableBytesTranscoder gifDrawableBytesTranscoder = new GifDrawableBytesTranscoder();</span><br><span class="line">    ContentResolver contentResolver = context.getContentResolver();</span><br><span class="line">    registry</span><br><span class="line">            .append(ByteBuffer.class, new ByteBufferEncoder())</span><br><span class="line">            .append(InputStream.class, new StreamEncoder(arrayPool))</span><br><span class="line">            .append(Integer.class, Uri.class, resourceLoaderUriFactory)</span><br><span class="line">            .append(int.class, Uri.class, resourceLoaderUriFactory)</span><br><span class="line">            .append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())</span><br><span class="line">            .append(Uri.class, InputStream.class, new AssetUriLoader.StreamFactory(context.getAssets()))</span><br><span class="line">            .append(byte[].class, ByteBuffer.class, new ByteArrayLoader.ByteBufferFactory())</span><br><span class="line">            .append(Drawable.class, Drawable.class, new UnitDrawableDecoder());</span><br><span class="line">    //此处省略若干代码.......</span><br><span class="line">    ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();</span><br><span class="line">    glideContext =</span><br><span class="line">            new GlideContext(</span><br><span class="line">                    context,</span><br><span class="line">                    arrayPool,</span><br><span class="line">                    registry,</span><br><span class="line">                    imageViewTargetFactory,</span><br><span class="line">                    defaultRequestOptions,</span><br><span class="line">                    defaultTransitionOptions,</span><br><span class="line">                    engine,</span><br><span class="line">                    logLevel);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里终于看到<code>append</code>方法是用来干嘛的了，第19行创建了一个<code>Registry()</code>对象，接着调用了一连串的<code>append</code>方法， 当然这里省略了很多其他<code>append()</code>逻辑，包括各种各样的类型。第34行也看到了之前用过的<code>glideContext</code>也在这里进行初始化了，在这些<code>append()</code>方法中，我们只需要关注<code>modelClass</code>为String的那些<code>append</code>方法，这里我筛选一下，直接上结果</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">append(String.class, InputStream .class, new DataUrlLoader.StreamFactory&lt;String&gt;())</span><br><span class="line">append(String.class, InputStream.class, new StringLoader.StreamFactory())</span><br><span class="line">append(String.class, ParcelFileDescriptor .class, new StringLoader.FileDescriptorFactory())</span><br><span class="line">append(String.class, AssetFileDescriptor .class, new StringLoader.AssetFileDescriptorFactory())</span><br></pre></td></tr></table></figure>
<p>如果还要追究这个<code>Glide(...)</code>是在哪里调用的，那可以看一下步骤1的第23行，<code>Glide.get(context).getRequestManagerRetriever()</code>，调用了<code>Glide.get()</code>方法，看下方的<code>get()</code>方法中调用<code>checkAndInitializeGlide()</code>，而<code>checkAndInitializeGlide()</code>方法会继续走<code>initializeGlide(context);</code>方法，接着大家就可以自己去看看了。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">@NonNull</span><br><span class="line">public static Glide get(@NonNull Context context) &#123;</span><br><span class="line">    if (glide == null) &#123;</span><br><span class="line">        synchronized (Glide.class) &#123;</span><br><span class="line">            if (glide == null) &#123;</span><br><span class="line">                checkAndInitializeGlide(context);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return glide;</span><br><span class="line">&#125;</span><br><span class="line">private static void checkAndInitializeGlide(@NonNull Context context) &#123;</span><br><span class="line">    if (isInitializing) &#123;</span><br><span class="line">        throw new IllegalStateException(&quot;You cannot call Glide.get() in registerComponents(),&quot;</span><br><span class="line">                + &quot; use the provided Glide instance instead&quot;);</span><br><span class="line">    &#125;</span><br><span class="line">    isInitializing = true;</span><br><span class="line">    initializeGlide(context);</span><br><span class="line">    isInitializing = false;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="步骤34：回到步骤29"><a href="#步骤34：回到步骤29" class="headerlink" title="步骤34：回到步骤29"></a>步骤34：回到步骤29</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">@NonNull</span><br><span class="line">synchronized &lt;Model&gt; List&lt;ModelLoader&lt;Model, ?&gt;&gt; build(@NonNull Class&lt;Model&gt; modelClass) &#123;</span><br><span class="line">    try &#123;</span><br><span class="line">        List&lt;ModelLoader&lt;Model, ?&gt;&gt; loaders = new ArrayList&lt;&gt;();</span><br><span class="line">        for (Entry&lt;?, ?&gt; entry : entries) &#123;</span><br><span class="line">            if (alreadyUsedEntries.contains(entry)) &#123;</span><br><span class="line">                continue;</span><br><span class="line">            &#125;</span><br><span class="line">            if (entry.handles(modelClass)) &#123;</span><br><span class="line">                alreadyUsedEntries.add(entry);</span><br><span class="line">                loaders.add(this.&lt;Model, Object&gt;build(entry));</span><br><span class="line">                alreadyUsedEntries.remove(entry);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        return loaders;</span><br><span class="line">    &#125; catch (Throwable t) &#123;</span><br><span class="line">        alreadyUsedEntries.clear();</span><br><span class="line">        throw t;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>既然我们知道了步骤29中的<code>entries</code>是什么，并且知道他里面放的是什么内容，那我们接着看步骤29的第9行，<code>entry.handles(modelClass)</code>，遍历每一个<code>entry</code>，调用<code>Entry#handles()</code>方法，接着来看一下<code>Entry#handles()</code></p>
<h2 id="步骤35：Entry-handles"><a href="#步骤35：Entry-handles" class="headerlink" title="步骤35：Entry#handles()"></a>步骤35：Entry#handles()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">private static class Entry&lt;Model, Data&gt; &#123;</span><br><span class="line">    private final Class&lt;Model&gt; modelClass;</span><br><span class="line">    @Synthetic</span><br><span class="line">    final Class&lt;Data&gt; dataClass;</span><br><span class="line">    @Synthetic final ModelLoaderFactory&lt;? extends Model, ? extends Data&gt; factory;</span><br><span class="line">    public Entry(</span><br><span class="line">            @NonNull Class&lt;Model&gt; modelClass,</span><br><span class="line">            @NonNull Class&lt;Data&gt; dataClass,</span><br><span class="line">            @NonNull ModelLoaderFactory&lt;? extends Model, ? extends Data&gt; factory) &#123;</span><br><span class="line">        this.modelClass = modelClass;</span><br><span class="line">        this.dataClass = dataClass;</span><br><span class="line">        this.factory = factory;</span><br><span class="line">    &#125;</span><br><span class="line">    public boolean handles(@NonNull Class&lt;?&gt; modelClass, @NonNull Class&lt;?&gt; dataClass) &#123;</span><br><span class="line">        return handles(modelClass) &amp;&amp; this.dataClass.isAssignableFrom(dataClass);</span><br><span class="line">    &#125;</span><br><span class="line">    public boolean handles(@NonNull Class&lt;?&gt; modelClass) &#123;</span><br><span class="line">        return this.modelClass.isAssignableFrom(modelClass);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上方代码是<code>Entry</code>类的所有代码，构造方法我们在之前已经看过了，第17行，<code>Entry#handles()</code>方法，其实内部就是判断传入的<code>modelClass</code>是不是当前<code>Entry</code>中的<code>modelClass</code>类型的子类，目前我们对<code>load(String)</code>做分析，这里的<code>modelClass</code>就是<code>String.class</code>。我们接下来要做的，就是把所有<code>modelClass</code>为String的<code>Entry</code>都拿出来调用步骤29的第11行<code>this.&lt;Model, Object&gt;build(entry)</code>，接着来看</p>
<h2 id="步骤36：MultiModelLoaderFactory-build"><a href="#步骤36：MultiModelLoaderFactory-build" class="headerlink" title="步骤36：MultiModelLoaderFactory#build()"></a>步骤36：MultiModelLoaderFactory#build()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">private &lt;Model, Data&gt; ModelLoader&lt;Model, Data&gt; build(@NonNull Entry&lt;?, ?&gt; entry) &#123;</span><br><span class="line">    return (ModelLoader&lt;Model, Data&gt;) Preconditions.checkNotNull(entry.factory.build(this));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第2行，<code>entry.factory.build(this)</code>，这里的<code>entry.factory</code>是<code>Entry</code>构造方法第3个参数，可以追溯到步骤33所罗列出来的关于<code>String</code>的那些<code>append()</code>方法的第3个参数，接下来我把这些<code>Factory的build()</code>方法都列出来</p>
<ol>
<li><p>DataUrlLoader.StreamFactory#build()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">public ModelLoader&lt;Model, InputStream&gt; build(</span><br><span class="line">        @NonNull MultiModelLoaderFactory multiFactory) &#123;</span><br><span class="line">    return new DataUrlLoader&lt;&gt;(opener);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>很简单，就是返回了DataUrlLoader()对象</p>
</li>
<li><p>StringLoader.StreamFactory#build()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">public ModelLoader&lt;String, InputStream&gt; build(</span><br><span class="line">        @NonNull MultiModelLoaderFactory multiFactory) &#123;</span><br><span class="line">    return new StringLoader&lt;&gt;(multiFactory.build(Uri.class, InputStream.class));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>外层看来是个StringLoader()对象，里面的multiFactory.build(Uri.class, InputStream.class)作为参数，传入到了StringLoader()对象中，里面的参数做了什么先放一放，我们继续往下看</p>
</li>
<li><p>StringLoader.FileDescriptorFactory#build()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">public ModelLoader&lt;String, ParcelFileDescriptor&gt; build(</span><br><span class="line">        @NonNull MultiModelLoaderFactory multiFactory) &#123;</span><br><span class="line">    return new StringLoader&lt;&gt;(multiFactory.build(Uri.class, ParcelFileDescriptor.class));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这个返回结果和第2个很像，不同的是第2个multiFactory.build(Uri.class, InputStream.class)，传入的参数Uri.class和InputStream.class，而这里将InputStream.class替换成了ParcelFileDescriptor.class</p>
</li>
<li><p>StringLoader.AssetFileDescriptorFactory#build()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">public ModelLoader&lt;String, AssetFileDescriptor&gt; build(</span><br><span class="line">        @NonNull MultiModelLoaderFactory multiFactory) &#123;</span><br><span class="line">    return new StringLoader&lt;&gt;(multiFactory.build(Uri.class, AssetFileDescriptor.class));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这个就不说了，也是同上</p>
</li>
</ol>
<h2 id="步骤37：MultiModelLoaderFactory-build-…"><a href="#步骤37：MultiModelLoaderFactory-build-…" class="headerlink" title="步骤37：MultiModelLoaderFactory#build(…)"></a>步骤37：MultiModelLoaderFactory#build(…)</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">public synchronized &lt;Model, Data&gt; ModelLoader&lt;Model, Data&gt; build(@NonNull Class&lt;Model&gt; modelClass,</span><br><span class="line">                                                                 @NonNull Class&lt;Data&gt; dataClass) &#123;</span><br><span class="line">    try &#123;</span><br><span class="line">        List&lt;ModelLoader&lt;Model, Data&gt;&gt; loaders = new ArrayList&lt;&gt;();</span><br><span class="line">        boolean ignoredAnyEntries = false;</span><br><span class="line">        for (Entry&lt;?, ?&gt; entry : entries) &#123;</span><br><span class="line">            if (alreadyUsedEntries.contains(entry)) &#123;</span><br><span class="line">                ignoredAnyEntries = true;</span><br><span class="line">                continue;</span><br><span class="line">            &#125;</span><br><span class="line">            if (entry.handles(modelClass, dataClass)) &#123;</span><br><span class="line">                alreadyUsedEntries.add(entry);</span><br><span class="line">                loaders.add(this.&lt;Model, Data&gt;build(entry));</span><br><span class="line">                alreadyUsedEntries.remove(entry);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        if (loaders.size() &gt; 1) &#123;</span><br><span class="line">            return factory.build(loaders, throwableListPool);</span><br><span class="line">        &#125; else if (loaders.size() == 1) &#123;</span><br><span class="line">            return loaders.get(0);</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            if (ignoredAnyEntries) &#123;</span><br><span class="line">                return emptyModelLoader();</span><br><span class="line">            &#125; else &#123;</span><br><span class="line">                throw new NoModelLoaderAvailableException(modelClass, dataClass);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; catch (Throwable t) &#123;</span><br><span class="line">        alreadyUsedEntries.clear();</span><br><span class="line">        throw t;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>接着我们来看下步骤36留下的问题<code>multiFactory.build(Uri.class, ...)</code>，这个<code>multiFactory</code>还是步骤36的<code>multiFactory</code>对象，也同样是<code>build()</code>方法，</p>
<blockquote>
<p>注意：</p>
<p>到这里我们总共用到了三个MultiModelLoaderFactory#build()方法，分别是步骤29，步骤36和当前步骤37，但是这3个build()方法不一样，步骤29的build()只有一个modelClass参数，步骤36的build传入的参数是Entry，而这个build()有两个参数，它比步骤29多了一个dataClass参数</p>
</blockquote>
<p>我们关注下第11行到第15行，再拿他和步骤29的代码对比一下，下方是步骤29的逻辑</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">if (entry.handles(modelClass)) &#123;</span><br><span class="line">    alreadyUsedEntries.add(entry);</span><br><span class="line">    loaders.add(this.&lt;Model, Object&gt;build(entry));</span><br><span class="line">    alreadyUsedEntries.remove(entry);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>它和步骤29很相似，只不过现在的<code>modelClass = Uri.class</code>，而<code>Entry</code>的<code>handles()</code>方法也变成了两个参数，通过步骤35第14行，我们了解到，<code>Entry#handles()</code>的这两个重载方法，都是判断传入的参数是否是子父类关系。然后在步骤37的13行继续<code>MultiModelLoaderFactory#build()</code>；</p>
<p>罗列一下关于<code>modelClass = Uri.class</code>并且的<code>dataClass = InputStream，ParcelFileDescriptor，AssetFileDescriptor</code>那些<code>append()</code>方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">append(Uri.class, InputStream.class, new DataUrlLoader.StreamFactory&lt;Uri&gt;())</span><br><span class="line">append(Uri.class, InputStream.class, new HttpUriLoader.Factory())</span><br><span class="line">append(Uri.class, InputStream.class, new AssetUriLoader.StreamFactory(context.getAssets()))</span><br><span class="line">append(Uri.class, ParcelFileDescriptor.class,new AssetUriLoader.FileDescriptorFactory(context.getAssets()))</span><br><span class="line">append(Uri.class, InputStream.class, new MediaStoreImageThumbLoader.Factory(context))</span><br><span class="line">append(Uri.class, InputStream.class, new MediaStoreVideoThumbLoader.Factory(context))</span><br><span class="line">append(Uri.class, InputStream.class,new UriLoader.StreamFactory(contentResolver))</span><br><span class="line">append(Uri.class, ParcelFileDescriptor.class,new UriLoader.FileDescriptorFactory(contentResolver))</span><br><span class="line">append(Uri.class, AssetFileDescriptor.class,new UriLoader.AssetFileDescriptorFactory(contentResolver))</span><br><span class="line">append(Uri.class, InputStream.class, new UrlUriLoader.StreamFactory())</span><br></pre></td></tr></table></figure>
<p>有10个相关，接下来就不一一带大家看了，随便列举几个看一下</p>
<h2 id="步骤38：MultiModelLoaderFactory-build-Entry"><a href="#步骤38：MultiModelLoaderFactory-build-Entry" class="headerlink" title="步骤38：MultiModelLoaderFactory#build(Entry)"></a>步骤38：MultiModelLoaderFactory#build(Entry)</h2><p>当前步骤和步骤36是一样的，通过上一步列举出来的10个关于<code>Uri.class</code>的重载方法，看一下对应的<code>Factory#build()</code>方法返回结果是什么，这里挑前两个看一下</p>
<ol>
<li><p>DataUrlLoader.StreamFactory#build()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">public ModelLoader&lt;Model, InputStream&gt; build(</span><br><span class="line">        @NonNull MultiModelLoaderFactory multiFactory) &#123;</span><br><span class="line">    return new DataUrlLoader&lt;&gt;(opener);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>HttpUriLoader.Factory#build()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public ModelLoader&lt;Uri, InputStream&gt; build(MultiModelLoaderFactory multiFactory) &#123;</span><br><span class="line">    return new HttpUriLoader(multiFactory.build(GlideUrl.class, InputStream.class));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第一个直接返回<code>DataUrlLoader</code>，而第二个又是在<code>HttpUriLoader</code>嵌套了<code>multiFactory.build(GlideUrl.class, InputStream.class)</code>，看到这里的命名方式我们可以大概猜到，这可能与<code>Http</code>请求相关了。既然又嵌套了<code>modelClass = GlideUrl.class</code>，那我们就去看一眼</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())</span><br></pre></td></tr></table></figure>
<p>在<code>Glide(...)</code>中就这么一个与<code>GlideUrl</code>相关的<code>append()</code>方法，那接着看一下这个<code>HttpGlideUrlLoader.Factory#build()</code>方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public ModelLoader&lt;GlideUrl, InputStream&gt; build(MultiModelLoaderFactory multiFactory) &#123;</span><br><span class="line">    return new HttpGlideUrlLoader(modelCache);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>得到了结果，是一个<code>HttpGlideUrlLoader</code>对象。</p>
</li>
<li><p>其它结果，如<code>AssetUriLoader.StreamFactory#build()</code>是一个<code>AssetUriLoader</code>对象。还有一些<code>MediaStoreImageThumbLoader</code>对象，就不带大家去看了，但其它结果也是条件成立的，需要放在返回的集合里，至于<code>Glide</code>怎么过滤不需要的<code>ModelLoader</code>的还不着急，还有其它细节等着去发现</p>
</li>
</ol>
<h2 id="步骤39：分析目前结果"><a href="#步骤39：分析目前结果" class="headerlink" title="步骤39：分析目前结果"></a>步骤39：分析目前结果</h2><p>我们在这里做一个小分析，小梳理，目前已经嵌套很多层， 都不知道最原始的目的是什么了。而且我们发现了<code>ModelLoader</code>这个类频繁出现，它是用来干嘛的，这个等到我们把主要流程分析完之后，就可以知道了。</p>
<ol>
<li>步骤29开始，我们希望找到与<code>String.class</code>相关的<code>ModelLoaders</code>集合，又发现是通过<code>Glide.with()</code>进入<code>Glide(...)</code>初始化的时候<code>append()</code>方法，初始化了<code>entries</code>集合，继而调用<code>entry.factory.build()</code>方法得到的<code>ModelLoaders</code>。</li>
<li>步骤36，我们又发现，并不是所有<code>factory</code>都能直接得到结果，其中还有嵌套关系，通过<code>modelClass = String.class</code>，引申到了步骤37，38，<code>modelClass = Uri.class</code>，进而分析了当<code>modelClass = Uri.class</code>的，那些对应的<code>Factory#build()</code>方法所产生的<code>ModelLoaders</code>集合。</li>
<li>在步骤38中又发现嵌套关系，这时<code>modelClass = GlideUrl.class</code>，好在<code>modelClass = GlideUrl.class</code>时没有再继续嵌套了。</li>
<li>最终得出，与<code>String.class</code>相关的<code>ModelLoader</code>层级关系如下<ul>
<li>DataUrlLoader</li>
<li>StringLoader<ul>
<li>DataUrlLoader</li>
<li>HttpUriLoader<ul>
<li>HttpGlideUrlLoader</li>
</ul>
</li>
<li>AssetUriLoader</li>
<li>MediaStoreImageThumbLoader</li>
<li>MediaStoreVideoThumbLoader</li>
<li>StreamLocalUriFetcher</li>
<li>UrlUriLoader<ul>
<li>HttpGlideUrlLoader</li>
</ul>
</li>
</ul>
</li>
<li>StringLoader<ul>
<li>UriLoader</li>
<li>AssetUriLoader</li>
</ul>
</li>
<li>StringLoader<ul>
<li>UriLoader</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>到这里结构已经很清晰了，但是还有一些细节等待处理，在步骤37的第17行到21行，此时<code>modelClass = Uri.class</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">if (loaders.size() &gt; 1) &#123;</span><br><span class="line">    return factory.build(loaders, throwableListPool);</span><br><span class="line">&#125; else if (loaders.size() == 1) &#123;</span><br><span class="line">    return loaders.get(0);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>如果loaders集合不止一个元素，比如上方第4点得出的结论，<code>StringLoader</code>中包含了7个<code>modelClass = Url.class</code>的结果，需要继续调用第2行<code>factory.build(loaders, throwableListPool);</code></p>
<h2 id="步骤40：Factory-build"><a href="#步骤40：Factory-build" class="headerlink" title="步骤40：Factory#build()"></a>步骤40：Factory#build()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">static class Factory &#123;</span><br><span class="line">    @NonNull</span><br><span class="line">    public &lt;Model, Data&gt; MultiModelLoader&lt;Model, Data&gt; build(</span><br><span class="line">            @NonNull List&lt;ModelLoader&lt;Model, Data&gt;&gt; modelLoaders,</span><br><span class="line">            @NonNull Pool&lt;List&lt;Throwable&gt;&gt; throwableListPool) &#123;</span><br><span class="line">        return new MultiModelLoader&lt;&gt;(modelLoaders, throwableListPool);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//下方是MultiModelLoader类代码</span><br><span class="line">class MultiModelLoader&lt;Model, Data&gt; implements ModelLoader&lt;Model, Data&gt; &#123;</span><br><span class="line">	private final List&lt;ModelLoader&lt;Model, Data&gt;&gt; modelLoaders;</span><br><span class="line">	private final Pool&lt;List&lt;Throwable&gt;&gt; exceptionListPool;</span><br><span class="line"></span><br><span class="line">	MultiModelLoader(@NonNull List&lt;ModelLoader&lt;Model, Data&gt;&gt; modelLoaders,</span><br><span class="line">                 	@NonNull Pool&lt;List&lt;Throwable&gt;&gt; exceptionListPool) &#123;</span><br><span class="line">    	this.modelLoaders = modelLoaders;</span><br><span class="line">    	this.exceptionListPool = exceptionListPool;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这个<code>Factory</code>是<code>MultiModelLoaderFactory</code>类中的一个内部类，第6行，将<code>modelLoaders</code>集合封装到一个<code>MultiModelLoader</code>对象中，而这个<code>MultiModelLoader</code>也是一个<code>ModelLoader</code>。所以其实在步骤39 中，第4点得出的结论需要更改，最准确的是<code>StringLoader</code>下应该包含了一个<code>MultiModelLoader</code></p>
<h2 id="步骤41：回到步骤29，返回最终结果"><a href="#步骤41：回到步骤29，返回最终结果" class="headerlink" title="步骤41：回到步骤29，返回最终结果"></a>步骤41：回到步骤29，返回最终结果</h2><p>到这一步，我们已经完成了关于<code>ModelLoader</code>的所有加载，首先回到步骤29第一段代码块第15行，返回了loaders集合，再回到步骤28，第6行，在cache里面保存了结果，第8行，往上层返回结果，来到步骤27，下方贴一下步骤27的代码</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">public &lt;A&gt; List&lt;ModelLoader&lt;A, ?&gt;&gt; getModelLoaders(@NonNull A model) &#123;</span><br><span class="line">    List&lt;ModelLoader&lt;A, ?&gt;&gt; modelLoaders = getModelLoadersForClass(getClass(model));</span><br><span class="line">    int size = modelLoaders.size();</span><br><span class="line">    boolean isEmpty = true;</span><br><span class="line">    List&lt;ModelLoader&lt;A, ?&gt;&gt; filteredLoaders = Collections.emptyList();</span><br><span class="line">    //noinspection ForLoopReplaceableByForEach to improve perf</span><br><span class="line">    for (int i = 0; i &lt; size; i++) &#123;</span><br><span class="line">        ModelLoader&lt;A, ?&gt; loader = modelLoaders.get(i);</span><br><span class="line">        if (loader.handles(model)) &#123;</span><br><span class="line">            if (isEmpty) &#123;</span><br><span class="line">                filteredLoaders = new ArrayList&lt;&gt;(size - i);</span><br><span class="line">                isEmpty = false;</span><br><span class="line">            &#125;</span><br><span class="line">            filteredLoaders.add(loader);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return filteredLoaders;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>我们第2行，<code>getModelLoadersForClass(getClass(model))</code>的结果已经得到了。看看接下来怎么做，第7行，遍历<code>modelLoaders</code>集合，然后在第9行，调用每个<code>loader.handles(model)</code>方法。并且我们在这里看到了另外一个集合，名称是<code>filteredLoaders</code>，看名字就知道，这里要开始过滤无效的<code>ModelLoader</code>了，那现在开始过滤</p>
<ol>
<li><p>DataUrlLoader#handles()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">public final class DataUrlLoader&lt;Model, Data&gt; implements ModelLoader&lt;Model, Data&gt; &#123;</span><br><span class="line">    private static final String DATA_SCHEME_IMAGE = &quot;data:image&quot;;</span><br><span class="line"></span><br><span class="line">    public boolean handles(@NonNull Model model) &#123;</span><br><span class="line">        return model.toString().startsWith(DATA_SCHEME_IMAGE);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第5行，很简单的逻辑，<code>return false;</code>那说明这个<code>ModelLoader</code>是不符合要求的。被过滤掉</p>
</li>
<li><p>StringLoader#handles()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public boolean handles(@NonNull String model) &#123;</span><br><span class="line">    return true;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>直接<code>return true</code>，说明剩下的3个<code>StringLoader</code>不用被过滤</p>
</li>
</ol>
<h2 id="步骤42：回到步骤25"><a href="#步骤42：回到步骤25" class="headerlink" title="步骤42：回到步骤25"></a>步骤42：回到步骤25</h2><p>步骤26不用看，就是一个判空的操作。直接看步骤25</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">List&lt;LoadData&lt;?&gt;&gt; getLoadData() &#123;</span><br><span class="line">    if (!isLoadDataSet) &#123;</span><br><span class="line">        isLoadDataSet = true;</span><br><span class="line">        loadData.clear();</span><br><span class="line">        List&lt;ModelLoader&lt;Object, ?&gt;&gt; modelLoaders = glideContext.getRegistry().getModelLoaders(model);</span><br><span class="line">        //noinspection ForLoopReplaceableByForEach to improve perf</span><br><span class="line">        for (int i = 0, size = modelLoaders.size(); i &lt; size; i++) &#123;</span><br><span class="line">            ModelLoader&lt;Object, ?&gt; modelLoader = modelLoaders.get(i);</span><br><span class="line">            LoadData&lt;?&gt; current =</span><br><span class="line">                    modelLoader.buildLoadData(model, width, height, options);</span><br><span class="line">            if (current != null) &#123;</span><br><span class="line">                loadData.add(current);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return loadData;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>现在第5行有了结果，接着在第10行，调用每个<code>modelLoader的buildLoadData()</code>方法；</p>
<h2 id="步骤43：StringLoader-buildLoadData"><a href="#步骤43：StringLoader-buildLoadData" class="headerlink" title="步骤43：StringLoader#buildLoadData()"></a>步骤43：StringLoader#buildLoadData()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">private final ModelLoader&lt;Uri, Data&gt; uriLoader;</span><br><span class="line"></span><br><span class="line">public LoadData&lt;Data&gt; buildLoadData(@NonNull String model, int width, int height,</span><br><span class="line">                                    @NonNull Options options) &#123;</span><br><span class="line">    Uri uri = parseUri(model);</span><br><span class="line">    if (uri == null || !uriLoader.handles(uri)) &#123;</span><br><span class="line">        return null;</span><br><span class="line">    &#125;</span><br><span class="line">    return uriLoader.buildLoadData(uri, width, height, options);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">private static Uri parseUri(String model) &#123;</span><br><span class="line">    Uri uri;</span><br><span class="line">    if (TextUtils.isEmpty(model)) &#123;</span><br><span class="line">        return null;</span><br><span class="line">    &#125; else if (model.charAt(0) == &apos;/&apos;) &#123;</span><br><span class="line">        uri = toFileUri(model);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        uri = Uri.parse(model);</span><br><span class="line">        String scheme = uri.getScheme();</span><br><span class="line">        if (scheme == null) &#123;</span><br><span class="line">            uri = toFileUri(model);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return uri;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>目前还剩3个<code>StringLoader</code>，来看下第5行，<code>parseUri()</code>方法，结果不会是null，所以看第6行的后面的条件<code>uriLoader.handles(uri)</code>结果，这里的<code>uriLoader</code>在第1行可以看到，他的类型是<code>ModelLoader</code>，我们在步骤40中得到这个<code>uriLoader</code>其实是<code>MultiModelLoader</code>。</p>
<h2 id="步骤44：MultiModelLoader-handles"><a href="#步骤44：MultiModelLoader-handles" class="headerlink" title="步骤44：MultiModelLoader#handles()"></a>步骤44：MultiModelLoader#handles()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">public boolean handles(@NonNull Model model) &#123;</span><br><span class="line">    for (ModelLoader&lt;Model, Data&gt; modelLoader : modelLoaders) &#123;</span><br><span class="line">        if (modelLoader.handles(model)) &#123;</span><br><span class="line">            return true;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return false;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第2行，显而易见，遍历所有的<code>modelLoaders</code>，调用<code>handles()</code>方法，如果这个<code>MultiModelLoader</code>中有任何一个<code>ModelLoader</code>满足条件，直接<code>return true；</code>因为数量有点多，而且<code>handles()</code>方法都是用来过滤的，所以我们挑几个<code>ModelLoader</code>看一下</p>
<ol>
<li><p>HttpUriLoader#handles()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">private static final Set&lt;String&gt; SCHEMES =</span><br><span class="line">        Collections.unmodifiableSet(new HashSet&lt;&gt;(Arrays.asList(&quot;http&quot;, &quot;https&quot;)));</span><br><span class="line"></span><br><span class="line">public boolean handles(@NonNull Uri model) &#123;</span><br><span class="line">    return SCHEMES.contains(model.getScheme());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>轻松得到结果，<code>return true</code>，满足条件</p>
</li>
<li><p>AssetUriLoader#handles()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">private static final String ASSET_PREFIX =</span><br><span class="line">      ContentResolver.SCHEME_FILE + &quot;:///&quot; + ASSET_PATH_SEGMENT + &quot;/&quot;;</span><br><span class="line"></span><br><span class="line">public boolean handles(@NonNull Uri model) &#123;</span><br><span class="line">    return ContentResolver.SCHEME_FILE.equals(model.getScheme()) &amp;&amp; !model.getPathSegments()</span><br><span class="line">            .isEmpty() &amp;&amp; ASSET_PATH_SEGMENT.equals(model.getPathSegments().get(0));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>很明显，<code>return false</code>，不满足条件</p>
</li>
</ol>
<p>最终，只有第一个<code>StringLoader</code>满足条件。继续回到步骤43的第9行，调用<code>uriLoader.buildLoadData()</code></p>
<h2 id="步骤45：MultiModelLoader-buildLoadData"><a href="#步骤45：MultiModelLoader-buildLoadData" class="headerlink" title="步骤45：MultiModelLoader#buildLoadData()"></a>步骤45：MultiModelLoader#buildLoadData()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">public LoadData&lt;Data&gt; buildLoadData(@NonNull Model model, int width, int height,</span><br><span class="line">                                    @NonNull Options options) &#123;</span><br><span class="line">    Key sourceKey = null;</span><br><span class="line">    int size = modelLoaders.size();</span><br><span class="line">    List&lt;DataFetcher&lt;Data&gt;&gt; fetchers = new ArrayList&lt;&gt;(size);</span><br><span class="line">    //noinspection ForLoopReplaceableByForEach to improve perf</span><br><span class="line">    for (int i = 0; i &lt; size; i++) &#123;</span><br><span class="line">        ModelLoader&lt;Model, Data&gt; modelLoader = modelLoaders.get(i);</span><br><span class="line">        if (modelLoader.handles(model)) &#123;</span><br><span class="line">            LoadData&lt;Data&gt; loadData = modelLoader.buildLoadData(model, width, height, options);</span><br><span class="line">            if (loadData != null) &#123;</span><br><span class="line">                sourceKey = loadData.sourceKey;</span><br><span class="line">                fetchers.add(loadData.fetcher);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return !fetchers.isEmpty() &amp;&amp; sourceKey != null</span><br><span class="line">            ? new LoadData&lt;&gt;(sourceKey, new MultiModelLoader.MultiFetcher&lt;&gt;(fetchers, exceptionListPool)) : null;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第9行，同样的逻辑，先判断<code>handles()</code>方法，然后调用符合条件的<code>ModelLoader#buildLoadData()</code>，这里直接告诉大家只有两个<code>ModelLoader</code>满足条件，分别是<code>HttpUriLoader</code>，<code>UrlUriLoader</code></p>
<p>HttpUriLoader#buildLoadData()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">public LoadData&lt;InputStream&gt; buildLoadData(@NonNull Uri model, int width, int height,</span><br><span class="line">                                           @NonNull Options options) &#123;</span><br><span class="line">    return urlLoader.buildLoadData(new GlideUrl(model.toString()), width, height, options);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>UrlUriLoader#buildLoadData()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">public LoadData&lt;Data&gt; buildLoadData(@NonNull Uri uri, int width, int height,</span><br><span class="line">                                    @NonNull Options options) &#123;</span><br><span class="line">    GlideUrl glideUrl = new GlideUrl(uri.toString());</span><br><span class="line">    return urlLoader.buildLoadData(glideUrl, width, height, options);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这两个<code>buildLoadData()</code>方法内部逻辑一样，首先封装<code>uri</code>变成一个<code>GlideUrl</code>对象，然后调用了<code>urlLoader.buildLoadData()</code>方法，这个<code>urlLoader</code>，之前在步骤39中提到过，是<code>HttpGlideUrlLoader</code>对象，因为之前不符合条件的<code>ModelLoader</code>已经被我们过滤掉了</p>
<p>HttpGlideUrlLoader#buildLoadData()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">public LoadData&lt;InputStream&gt; buildLoadData(@NonNull GlideUrl model, int width, int height,</span><br><span class="line">                                           @NonNull Options options) &#123;</span><br><span class="line">    GlideUrl url = model;</span><br><span class="line">    if (modelCache != null) &#123;</span><br><span class="line">        url = modelCache.get(model, 0, 0);</span><br><span class="line">        if (url == null) &#123;</span><br><span class="line">            modelCache.put(model, 0, 0, model);</span><br><span class="line">            url = model;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    int timeout = options.get(TIMEOUT);</span><br><span class="line">    return new LoadData&lt;&gt;(url, new HttpUrlFetcher(url, timeout));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上方第12行，<code>return new LoadData&lt;&gt;(url, new HttpUrlFetcher(url, timeout));</code>再看此步骤第一段代码第18行，如果<code>fetchers</code>集合不为空，那么同样会封装成一个<code>MultiFetcher</code>返回。回到步骤25或步骤42，看步骤42的第12行，<code>loadData.add(current);</code>所有非null的<code>LoadData</code>都加入到了<code>LoadData</code>集合中</p>
<h2 id="步骤46：回到步骤24"><a href="#步骤46：回到步骤24" class="headerlink" title="步骤46：回到步骤24"></a>步骤46：回到步骤24</h2><p>步骤24第6行，离的比较远了，我这里贴一下代码</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">for (int i = 0, size = loadData.size(); i &lt; size; i++) &#123;</span><br><span class="line">    LoadData&lt;?&gt; data = loadData.get(i);</span><br><span class="line">    if (!cacheKeys.contains(data.sourceKey)) &#123;</span><br><span class="line">        cacheKeys.add(data.sourceKey);</span><br><span class="line">    &#125;</span><br><span class="line">    for (int j = 0; j &lt; data.alternateKeys.size(); j++) &#123;</span><br><span class="line">        if (!cacheKeys.contains(data.alternateKeys.get(j))) &#123;</span><br><span class="line">            cacheKeys.add(data.alternateKeys.get(j));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">return cacheKeys;</span><br></pre></td></tr></table></figure>
<p>遍历<code>loadData</code>集合，然后操作<code>cacheKeys</code>和<code>alternateKeys</code>两个集合，其中第3行，<code>data.sourceKey</code>指向的是图片url地址，这些不是主要逻辑，简单过一下，最终<code>return cacheKeys;</code>再回到步骤23第3行，判断<code>cacheKeys</code>是否为空，这里是不为空的，因为已经在<code>cacheKeys</code>中添加过<code>data.sourceKey</code>了。接着看步骤23第6行，<code>List&lt;Class&lt;?&gt;&gt; resourceClasses = helper.getRegisteredResourceClasses();</code></p>
<h2 id="步骤47：DecodeHelper-getRegisteredResourceClasses"><a href="#步骤47：DecodeHelper-getRegisteredResourceClasses" class="headerlink" title="步骤47：DecodeHelper#getRegisteredResourceClasses()"></a>步骤47：DecodeHelper#getRegisteredResourceClasses()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">List&lt;Class&lt;?&gt;&gt; getRegisteredResourceClasses() &#123;</span><br><span class="line">    return glideContext.getRegistry()</span><br><span class="line">            .getRegisteredResourceClasses(model.getClass(), resourceClass, transcodeClass);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这一步骤主要讲的是资源类型的匹配，属于次要逻辑，简单过一下之后会直接告诉大家结果，接着代码第3行，继续往下，又一次来到<code>Registry#getRegisteredResourceClasses()</code>，传入的三个参数，第一个<code>model</code>不用说了；<code>resourceClass</code>指的是<code>Object.class</code>，因为我们什么都没有指定；<code>transcodeClass</code>指的是<code>Drawable.class</code>，这是一开始Glide默认使用<code>asDrawable()</code>指定的</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">public &lt;Model, TResource, Transcode&gt; List&lt;Class&lt;?&gt;&gt; getRegisteredResourceClasses(</span><br><span class="line">        @NonNull Class&lt;Model&gt; modelClass, @NonNull Class&lt;TResource&gt; resourceClass,</span><br><span class="line">        @NonNull Class&lt;Transcode&gt; transcodeClass) &#123;</span><br><span class="line">    List&lt;Class&lt;?&gt;&gt; result = modelToResourceClassCache.get(modelClass, resourceClass);</span><br><span class="line">    if (result == null) &#123;</span><br><span class="line">        result = new ArrayList&lt;&gt;();</span><br><span class="line">        List&lt;Class&lt;?&gt;&gt; dataClasses = modelLoaderRegistry.getDataClasses(modelClass);</span><br><span class="line">        for (Class&lt;?&gt; dataClass : dataClasses) &#123;</span><br><span class="line">            List&lt;? extends Class&lt;?&gt;&gt; registeredResourceClasses =</span><br><span class="line">                    decoderRegistry.getResourceClasses(dataClass, resourceClass);</span><br><span class="line">            for (Class&lt;?&gt; registeredResourceClass : registeredResourceClasses) &#123;</span><br><span class="line">                List&lt;Class&lt;Transcode&gt;&gt; registeredTranscodeClasses = transcoderRegistry</span><br><span class="line">                        .getTranscodeClasses(registeredResourceClass, transcodeClass);</span><br><span class="line">                if (!registeredTranscodeClasses.isEmpty() &amp;&amp; !result.contains(registeredResourceClass)) &#123;</span><br><span class="line">                    result.add(registeredResourceClass);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        modelToResourceClassCache.put(modelClass, resourceClass,</span><br><span class="line">                Collections.unmodifiableList(result));</span><br><span class="line">    &#125;</span><br><span class="line">    return result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上方代码第7行，<code>modelLoaderRegistry.getDataClasses(modelClass)</code>，下方代码第2行，继续跳转到MultiModelLoaderFactory#getDataClasses()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public synchronized List&lt;Class&lt;?&gt;&gt; getDataClasses(@NonNull Class&lt;?&gt; modelClass) &#123;</span><br><span class="line">    return multiModelLoaderFactory.getDataClasses(modelClass);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>MultiModelLoaderFactory#getDataClasses()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">synchronized List&lt;Class&lt;?&gt;&gt; getDataClasses(@NonNull Class&lt;?&gt; modelClass) &#123;</span><br><span class="line">    List&lt;Class&lt;?&gt;&gt; result = new ArrayList&lt;&gt;();</span><br><span class="line">    for (Entry&lt;?, ?&gt; entry : entries) &#123;</span><br><span class="line">        if (!result.contains(entry.dataClass) &amp;&amp; entry.handles(modelClass)) &#123;</span><br><span class="line">            result.add(entry.dataClass);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>将<code>entry.dataClass</code>加入到集合，最终返回。在步骤33我们已经分析过了，这里的<code>dataClass</code>有3个，分别是<code>InputStream</code>，<code>ParcelFileDescriptor</code>，<code>AssetFileDescriptor</code>，继续看步骤47第2块代码第10行<code>decoderRegistry.getResourceClasses()；</code></p>
<p>ResourceDecoderRegistry#getResourceClasses()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">public synchronized &lt;T, R&gt; List&lt;Class&lt;R&gt;&gt; getResourceClasses(@NonNull Class&lt;T&gt; dataClass,</span><br><span class="line">                                                             @NonNull Class&lt;R&gt; resourceClass) &#123;</span><br><span class="line">    List&lt;Class&lt;R&gt;&gt; result = new ArrayList&lt;&gt;();</span><br><span class="line">    for (String bucket : bucketPriorityList) &#123;</span><br><span class="line">        List&lt;Entry&lt;?, ?&gt;&gt; entries = decoders.get(bucket);</span><br><span class="line">        if (entries == null) &#123;</span><br><span class="line">            continue;</span><br><span class="line">        &#125;</span><br><span class="line">        for (Entry&lt;?, ?&gt; entry : entries) &#123;</span><br><span class="line">            if (entry.handles(dataClass, resourceClass)</span><br><span class="line">                    &amp;&amp; !result.contains((Class&lt;R&gt;) entry.resourceClass)) &#123;</span><br><span class="line">                result.add((Class&lt;R&gt;) entry.resourceClass);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第4行，这里我们看到一开始就遍历了<code>bucketPriorityList</code>，下面直接告诉大家<code>bucketPriorityList</code>是通过<code>ResourceDecoderRegistry#setBucketPriorityList()</code>初始化的，而<code>ResourceDecoderRegistry#setBucketPriorityList()</code>方法最终是被<code>Registry</code>的构造方法调用，传入的List内容是<code>BUCKET_GIF</code>, <code>BUCKET_BITMAP</code>, <code>BUCKET_BITMAP_DRAWABLE</code>,<code>BUCKET_PREPEND_ALL</code>,<code>BUCKET_APPEND_ALL</code>，接着第5行<code>decoders.get(bucket)；</code>说明<code>decoders</code>也是初始化好的，<code>decoders</code>最初也是通过<code>registry.append(...)</code>方法初始化的，只不过不是上面提到过的<code>append()</code>方法，而是另一个重载方法。接着第12行，在层层循环里面，用同样的，<code>entry.handles()</code>方法判断是否与当前的<code>dataClass</code>, <code>resourceClass</code>相匹配，将匹配后的结果放入<code>result</code>集合最终返回。</p>
<blockquote>
<p>大概介绍了result的内容之后，接着我们直接回到步骤23的第6行看下最终结果</p>
</blockquote>
<p>result中最终有3个对象，<code>GifDrawable</code>,<code>Bitmap</code>,<code>BitpmapDrawable</code>，步骤23的第7行，判断<code>result</code>是否为空，很显然不是空，那继续往下走</p>
<h2 id="步骤48：回到步骤23"><a href="#步骤48：回到步骤23" class="headerlink" title="步骤48：回到步骤23"></a>步骤48：回到步骤23</h2><p>到现在为止，我们只分析了，步骤23的前两个主要逻辑，然而还没有得到想要的结果，我们接着往下看。步骤23第12到40行</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">while (modelLoaders == null || !hasNextModelLoader()) &#123;</span><br><span class="line">  resourceClassIndex++;</span><br><span class="line">  if (resourceClassIndex &gt;= resourceClasses.size()) &#123;</span><br><span class="line">    sourceIdIndex++;</span><br><span class="line">    if (sourceIdIndex &gt;= sourceIds.size()) &#123;</span><br><span class="line">      return false;</span><br><span class="line">    &#125;</span><br><span class="line">    resourceClassIndex = 0;</span><br><span class="line">  &#125;</span><br><span class="line">  Key sourceId = sourceIds.get(sourceIdIndex);</span><br><span class="line">  Class&lt;?&gt; resourceClass = resourceClasses.get(resourceClassIndex);</span><br><span class="line">  Transformation&lt;?&gt; transformation = helper.getTransformation(resourceClass);</span><br><span class="line">  currentKey =</span><br><span class="line">      new ResourceCacheKey(// NOPMD AvoidInstantiatingObjectsInLoops</span><br><span class="line">          helper.getArrayPool(),</span><br><span class="line">          sourceId,</span><br><span class="line">          helper.getSignature(),</span><br><span class="line">          helper.getWidth(),</span><br><span class="line">          helper.getHeight(),</span><br><span class="line">          transformation,</span><br><span class="line">          resourceClass,</span><br><span class="line">          helper.getOptions());</span><br><span class="line">  cacheFile = helper.getDiskCache().get(currentKey);</span><br><span class="line">  if (cacheFile != null) &#123;</span><br><span class="line">    sourceKey = sourceId;</span><br><span class="line">    modelLoaders = helper.getModelLoaders(cacheFile);</span><br><span class="line">    modelLoaderIndex = 0;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里是个while循环，第一个条件<code>modelLoaders == null</code> 成立，注意这里的<code>modelLoaders</code>是<code>ResourceCacheGenerator</code>的成员变量，和<code>decoderHelper</code>中的不一样，所以循环是成立的。接下来看看循环中做了什么事。</p>
<ol>
<li>第2行，<code>resourceClassIndex</code>初始值为-1，每一次循环都+1，一开始第3行的条件肯定是不成立的</li>
<li>从第10行到23行，可以看到都是缓存的逻辑，第23行的<code>helper.getDiskCache()</code>表示从磁盘中获取缓存，在第24行判断缓存是否为null，第一次加载缓存肯定不存在</li>
<li>由于缓存不存在，最终会因为第3行条件为true，进而判断第5行条件，而第5行条件也随着索引的增加，最终在第6行<code>return false；</code></li>
</ol>
<p>到这里，步骤23：<code>ResourceCacheGenerator#startNext()</code>方法已经分析结束了。</p>
<h2 id="步骤49：DecodeJob-runGenerators"><a href="#步骤49：DecodeJob-runGenerators" class="headerlink" title="步骤49：DecodeJob#runGenerators()"></a>步骤49：DecodeJob#runGenerators()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">private void runGenerators() &#123;</span><br><span class="line">    currentThread = Thread.currentThread();</span><br><span class="line">    startFetchTime = LogTime.getLogTime();</span><br><span class="line">    boolean isStarted = false;</span><br><span class="line">    while (!isCancelled &amp;&amp; currentGenerator != null</span><br><span class="line">            &amp;&amp; !(isStarted = currentGenerator.startNext())) &#123;</span><br><span class="line">        stage = getNextStage(stage);</span><br><span class="line">        currentGenerator = getNextGenerator();</span><br><span class="line">        if (stage == Stage.SOURCE) &#123;</span><br><span class="line">            reschedule();</span><br><span class="line">            return;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    if ((stage == Stage.FINISHED || isCancelled) &amp;&amp; !isStarted) &#123;</span><br><span class="line">        notifyFailed();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>从步骤48开始，我们结束了第一个<code>Generator</code>，也就是<code>ResourceCacheGenerator</code>，接下来就是继续走步骤22的代码，这里重新贴了一下。在步骤48，我们知道<code>ResourceCacheGenerator#startNext()</code>最后兜兜转转<code>return false;</code>赋值给第6行<code>isStarted = false;</code>那么第5行到第13行的while循环条件就成立了。第7行，继续<code>getNextStage(stage)；</code>当前<code>stage</code>状态已经被更改了，最新状态为<code>stage = Stage.RESOURCE_CACHE;</code>传入到<code>getNextStage()</code>方法中，继续看步骤19第7行，<code>diskCacheStrategy.decodeCachedData() ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE)</code>，这个<code>diskCacheStrategy</code>还是之前步骤20提到的<code>AUTOMATIC</code>，从而得知<code>AUTOMATIC#decodeCachedData()</code>也是<code>return true;</code>所以当前<code>stage = Stage.DATA_CACHE;</code>看第8行，再次<code>getNextGenerator()</code>，回看步骤21第6行得知<code>currentGenerator = DataCacheGenerator()；</code>贴一下最新的状态</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">runReason = RunReason.INITIALIZE</span><br><span class="line">stage = Stage.DATA_CACHE</span><br><span class="line">currentGenerator = new DataCacheGenerator()</span><br></pre></td></tr></table></figure>
<h2 id="步骤50：DataCacheGenerator-startNext"><a href="#步骤50：DataCacheGenerator-startNext" class="headerlink" title="步骤50：DataCacheGenerator#startNext()"></a>步骤50：DataCacheGenerator#startNext()</h2><p>再次判断步骤49的第5行，while条件，这次执行的是<code>DataCacheGenerator#startNext()</code>方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">public boolean startNext() &#123;</span><br><span class="line">    while (modelLoaders == null || !hasNextModelLoader()) &#123;</span><br><span class="line">        sourceIdIndex++;</span><br><span class="line">        if (sourceIdIndex &gt;= cacheKeys.size()) &#123;</span><br><span class="line">            return false;</span><br><span class="line">        &#125;</span><br><span class="line">        Key sourceId = cacheKeys.get(sourceIdIndex);</span><br><span class="line">        @SuppressWarnings(&quot;PMD.AvoidInstantiatingObjectsInLoops&quot;)</span><br><span class="line">        Key originalKey = new DataCacheKey(sourceId, helper.getSignature());</span><br><span class="line">        cacheFile = helper.getDiskCache().get(originalKey);</span><br><span class="line">        if (cacheFile != null) &#123;</span><br><span class="line">            this.sourceKey = sourceId;</span><br><span class="line">            modelLoaders = helper.getModelLoaders(cacheFile);</span><br><span class="line">            modelLoaderIndex = 0;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    loadData = null;</span><br><span class="line">    boolean started = false;</span><br><span class="line">    while (!started &amp;&amp; hasNextModelLoader()) &#123;</span><br><span class="line">        ModelLoader&lt;File, ?&gt; modelLoader = modelLoaders.get(modelLoaderIndex++);</span><br><span class="line">        loadData =</span><br><span class="line">                modelLoader.buildLoadData(cacheFile, helper.getWidth(), helper.getHeight(),</span><br><span class="line">                        helper.getOptions());</span><br><span class="line">        if (loadData != null &amp;&amp; helper.hasLoadPath(loadData.fetcher.getDataClass())) &#123;</span><br><span class="line">            started = true;</span><br><span class="line">            loadData.fetcher.loadData(helper.getPriority(), this);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return started;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第2行，这里的<code>modelLoaders == null</code>，和<code>ResourceCacheGenerator</code>中的<code>modelLoaders</code>一样是自身的成员变量，第一个条件满足，直接进入循环，第3到6行，不用解释了，还是和<code>ResourceCacheGenerator</code>一样的索引自增逻辑，一开始<code>sourceIdIndex = -1；</code>接着看第7行，<code>cacheKeys.get(sourceIdIndex);</code>这个<code>cacheKeys</code>集合，我们在分析<code>ResourceCacheGenerator#startNext()</code>时发现也有同样的<code>cacheKeys</code>集合，我们来看下<code>DataCacheGenerator</code>的构造方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">DataCacheGenerator(DecodeHelper&lt;?&gt; helper, FetcherReadyCallback cb) &#123;</span><br><span class="line">    this(helper.getCacheKeys(), helper, cb);</span><br><span class="line">&#125;</span><br><span class="line">DataCacheGenerator(List&lt;Key&gt; cacheKeys, DecodeHelper&lt;?&gt; helper, FetcherReadyCallback cb) &#123;</span><br><span class="line">    this.cacheKeys = cacheKeys;</span><br><span class="line">    this.helper = helper;</span><br><span class="line">    this.cb = cb;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>从第2行和第5行就可以知道，这个<code>cacheKeys</code>其实就是在步骤23的第2行得到的<code>cacheKeys</code>，因为<code>DataCacheGenerator</code>和<code>ResourceCacheGenerator</code>用的是同一个<code>DecodeHelper</code>对象。了解了<code>cacheKeys</code>之后，我们接着往下看，此步骤，第一段代码，第10行和第11行，同样是判断磁盘缓存，同样结果是null，最后也是在第一段代码的第5行<code>return false;</code></p>
<h2 id="步骤51：回到步骤49执行循环"><a href="#步骤51：回到步骤49执行循环" class="headerlink" title="步骤51：回到步骤49执行循环"></a>步骤51：回到步骤49执行循环</h2><p>步骤49第7行，第8行，当前状态是</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">runReason = RunReason.INITIALIZE</span><br><span class="line">stage = Stage.DATA_CACHE</span><br><span class="line">currentGenerator = new DataCacheGenerator()</span><br></pre></td></tr></table></figure>
<p>贴一小段代码：getNextStage()方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">case DATA_CACHE:</span><br><span class="line">  return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;</span><br></pre></td></tr></table></figure>
<p>这边有疑问了，<code>onlyRetrieveFromCache</code>是什么？看名字其实就能知道，这个flag用来判断是否只从缓存中加载数据，很显然<code>onlyRetrieveFromCache = false；</code>接着执行<code>getNextGenerator()</code></p>
<p>执行完之后最新状态是</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">runReason = RunReason.INITIALIZE</span><br><span class="line">stage = Stage.SOURCE</span><br><span class="line">currentGenerator = new SourceGenerator()</span><br></pre></td></tr></table></figure>
<p>继续看步骤49的第9到12行</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">if (stage == Stage.SOURCE) &#123;</span><br><span class="line">    reschedule();</span><br><span class="line">    return;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这时候，<code>stage = Stage.SOURCE</code>，执行<code>reschedule();</code>并且直接<code>return</code>，导致<code>DecodeJob#runGenerators()</code>直接结束。继续看<code>reschedule()</code>方法</p>
<h2 id="步骤52：DecodeJob-reschedule"><a href="#步骤52：DecodeJob-reschedule" class="headerlink" title="步骤52：DecodeJob#reschedule()"></a>步骤52：DecodeJob#reschedule()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">public void reschedule() &#123;</span><br><span class="line">    runReason = DecodeJob.RunReason.SWITCH_TO_SOURCE_SERVICE;</span><br><span class="line">    callback.reschedule(this);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>很简单的逻辑，<code>runReason</code>被更改为<code>RunReason.SWITCH_TO_SOURCE_SERVICE</code>，继而执行<code>callback.reschedule(this)</code>，这个<code>callback</code>我们需要去找一下，首先是在源码中通过<code>DecodeJob#init()</code>方法传入，最终追溯到步骤15第72行，就是<code>engineJob</code>对象</p>
<h2 id="步骤53：EngineJob-reschedule"><a href="#步骤53：EngineJob-reschedule" class="headerlink" title="步骤53：EngineJob#reschedule()"></a>步骤53：EngineJob#reschedule()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public void reschedule(DecodeJob&lt;?&gt; job) &#123;</span><br><span class="line">    getActiveSourceExecutor().execute(job);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>同样很简单，这边换了个线程池，再重新执行<code>DecodeJob的run()</code>方法（想要知道原先线程所在的线程池的同学就自己去找一下吧，参考步骤16第3行），我们再次回到步骤17第10行，<code>runWrapped()</code>方法，接着步骤18第8行到10行，因为经过步骤52，<code>runReason</code>状态被更改为<code>RunReason.SWITCH_TO_SOURCE_SERVICE</code>，所以会执行以下代码：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">case SWITCH_TO_SOURCE_SERVICE:</span><br><span class="line">        runGenerators();</span><br><span class="line">        break;</span><br></pre></td></tr></table></figure>
<p>又要执行<code>runGenerators();</code>那我们再回到步骤49，关键方法还是步骤49第6行，目前<code>currentGenerator = new SourceGenerator()</code></p>
<h2 id="步骤54：SourceGenerator-startNext"><a href="#步骤54：SourceGenerator-startNext" class="headerlink" title="步骤54：SourceGenerator#startNext()"></a>步骤54：SourceGenerator#startNext()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">public boolean startNext() &#123;</span><br><span class="line">    if (dataToCache != null) &#123;</span><br><span class="line">        Object data = dataToCache;</span><br><span class="line">        dataToCache = null;</span><br><span class="line">        cacheData(data);</span><br><span class="line">    &#125;</span><br><span class="line">    if (sourceCacheGenerator != null &amp;&amp; sourceCacheGenerator.startNext()) &#123;</span><br><span class="line">        return true;</span><br><span class="line">    &#125;</span><br><span class="line">    sourceCacheGenerator = null;</span><br><span class="line">    loadData = null;</span><br><span class="line">    boolean started = false;</span><br><span class="line">    while (!started &amp;&amp; hasNextModelLoader()) &#123;</span><br><span class="line">        loadData = helper.getLoadData().get(loadDataListIndex++);</span><br><span class="line">        if (loadData != null</span><br><span class="line">                &amp;&amp; (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())</span><br><span class="line">                || helper.hasLoadPath(loadData.fetcher.getDataClass()))) &#123;</span><br><span class="line">            started = true;</span><br><span class="line">            loadData.fetcher.loadData(helper.getPriority(), this);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return started;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">private boolean hasNextModelLoader() &#123;</span><br><span class="line">    return loadDataListIndex &lt; helper.getLoadData().size();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第2行<code>dataToCache</code>和第7行<code>sourceCacheGenerator</code>都是他内部的成员变量，初始值是null，所以来到第13行第一个条件started在第12行刚被赋值为false，所以关键看第二个条件<code>hasNextModelLoader()</code>的返回结果，第25行，首先<code>loadDataListIndex</code>在<code>SourceGenerator</code>中被初始化为默认值0，<code>helper.getLoadData().size()</code>这个结果参照步骤25，42，45就可以得到，所以循环条件成立。第14行，拿到<code>loadData</code>对象，第15行，<code>loadData</code>这里不会是null，因为我们之前已经得到实例了，只需要判断<code>helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())</code>这个条件就可以了，先看里面<code>loadData.fetcher.getDataSource()</code>，这个<code>loadData.fetcher</code>参考步骤45，可以得到<code>fetcher</code>是<code>MultiFetcher</code>。</p>
<p>MultiFetcher#getDataSource()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public DataSource getDataSource() &#123;</span><br><span class="line">    return fetchers.get(0).getDataSource();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第2行<code>fetchers.get(0)</code>，这里面的fetcher其实都是<code>HttpUrlFetcher</code>，同样参照步骤45</p>
<p>HttpUrlFetcher#getDataSource()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public DataSource getDataSource() &#123;</span><br><span class="line">    return DataSource.REMOTE;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><code>diskCacheStrategy</code>在步骤20就提到过是<code>AUTOMATIC</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public boolean isDataCacheable(DataSource dataSource) &#123;</span><br><span class="line">    return dataSource == DataSource.REMOTE;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>综上，条件成立，继续执行此步骤第18行<code>started = true;</code>可见执行完一次<code>loadData</code>方法之后就要跳出循环了，<code>startNext()</code>方法<code>return true；</code>这里<code>return true</code>之后，<code>DecodeJob#runGenerators()</code>方法也执行完毕。第19行，<code>loadData.fetcher.loadData(helper.getPriority(), this);</code>执行<code>MultiFetcher#loadData()</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">public void loadData(</span><br><span class="line">        @NonNull Priority priority, @NonNull DataCallback&lt;? super Data&gt; callback) &#123;</span><br><span class="line">    this.priority = priority;</span><br><span class="line">    this.callback = callback;</span><br><span class="line">    exceptions = throwableListPool.acquire();</span><br><span class="line">    fetchers.get(currentIndex).loadData(priority, this);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第6行，其实就是<code>HttpUrlFetcher#loadData()</code>方法</p>
<h2 id="步骤55：HttpUrlFetcher-loadData"><a href="#步骤55：HttpUrlFetcher-loadData" class="headerlink" title="步骤55：HttpUrlFetcher#loadData()"></a>步骤55：HttpUrlFetcher#loadData()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line">public void loadData(@NonNull Priority priority,</span><br><span class="line">                     @NonNull DataCallback&lt;? super InputStream&gt; callback) &#123;</span><br><span class="line">    long startTime = LogTime.getLogTime();</span><br><span class="line">    try &#123;</span><br><span class="line">        InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());</span><br><span class="line">        callback.onDataReady(result);</span><br><span class="line">    &#125; catch (IOException e) &#123;</span><br><span class="line">        if (Log.isLoggable(TAG, Log.DEBUG)) &#123;</span><br><span class="line">            Log.d(TAG, &quot;Failed to load data for url&quot;, e);</span><br><span class="line">        &#125;</span><br><span class="line">        callback.onLoadFailed(e);</span><br><span class="line">    &#125; finally &#123;</span><br><span class="line">        if (Log.isLoggable(TAG, Log.VERBOSE)) &#123;</span><br><span class="line">            Log.v(TAG, &quot;Finished http url fetcher fetch in &quot; + LogTime.getElapsedMillis(startTime));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,</span><br><span class="line">                                          Map&lt;String, String&gt; headers) throws IOException &#123;</span><br><span class="line">    if (redirects &gt;= MAXIMUM_REDIRECTS) &#123;</span><br><span class="line">        throw new HttpException(&quot;Too many (&gt; &quot; + MAXIMUM_REDIRECTS + &quot;) redirects!&quot;);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        try &#123;</span><br><span class="line">            if (lastUrl != null &amp;&amp; url.toURI().equals(lastUrl.toURI())) &#123;</span><br><span class="line">                throw new HttpException(&quot;In re-direct loop&quot;);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; catch (URISyntaxException e) &#123;</span><br><span class="line">            // Do nothing, this is best effort.</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    urlConnection = connectionFactory.build(url);</span><br><span class="line">    for (Map.Entry&lt;String, String&gt; headerEntry : headers.entrySet()) &#123;</span><br><span class="line">        urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());</span><br><span class="line">    &#125;</span><br><span class="line">    urlConnection.setConnectTimeout(timeout);</span><br><span class="line">    urlConnection.setReadTimeout(timeout);</span><br><span class="line">    urlConnection.setUseCaches(false);</span><br><span class="line">    urlConnection.setDoInput(true);</span><br><span class="line">    urlConnection.setInstanceFollowRedirects(false);</span><br><span class="line">    urlConnection.connect();</span><br><span class="line">    stream = urlConnection.getInputStream();</span><br><span class="line">    if (isCancelled) &#123;</span><br><span class="line">        return null;</span><br><span class="line">    &#125;</span><br><span class="line">    final int statusCode = urlConnection.getResponseCode();</span><br><span class="line">    if (isHttpOk(statusCode)) &#123;</span><br><span class="line">        return getStreamForSuccessfulRequest(urlConnection);</span><br><span class="line">    &#125; else if (isHttpRedirect(statusCode)) &#123;</span><br><span class="line">        String redirectUrlString = urlConnection.getHeaderField(&quot;Location&quot;);</span><br><span class="line">        if (TextUtils.isEmpty(redirectUrlString)) &#123;</span><br><span class="line">            throw new HttpException(&quot;Received empty or null redirect url&quot;);</span><br><span class="line">        &#125;</span><br><span class="line">        URL redirectUrl = new URL(url, redirectUrlString);</span><br><span class="line">        cleanup();</span><br><span class="line">        return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);</span><br><span class="line">    &#125; else if (statusCode == INVALID_STATUS_CODE) &#123;</span><br><span class="line">        throw new HttpException(statusCode);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        throw new HttpException(urlConnection.getResponseMessage(), statusCode);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第5行，<code>loadDataWithRedirects</code>，继而跳转到第20行，终于看到了熟悉的<code>HttpURLConnection</code>，这里就是真正的网络访问的逻辑了。然而还没有结束，我们还要返回到界面进行展示。第6行<code>callback.onDataReady(result)；</code>这个<code>callback</code>是<code>MultiFetcher</code></p>
<p>MultiFetcher#onDataReady()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">public void onDataReady(@Nullable Data data) &#123;</span><br><span class="line">    if (data != null) &#123;</span><br><span class="line">        callback.onDataReady(data);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        startNextOrFail();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第3行，如果网络加载成功了，就继续回调callback，如果没有成功，继续执行<code>startNextOrFail()</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">private void startNextOrFail() &#123;</span><br><span class="line">    if (currentIndex &lt; fetchers.size() - 1) &#123;</span><br><span class="line">        currentIndex++;</span><br><span class="line">        loadData(priority, callback);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        Preconditions.checkNotNull(exceptions);</span><br><span class="line">        callback.onLoadFailed(new GlideException(&quot;Fetch failed&quot;, new ArrayList&lt;&gt;(exceptions)));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>可以看到，其实就是执行下一个<code>Fetcher</code>，这里我们假设成功了。直接回调<code>callback.onDataReady(data);</code>，这里的callback就是步骤54中的<code>SourceGenerator</code>对象</p>
<h2 id="步骤56：SourceGenerator-onDataReady"><a href="#步骤56：SourceGenerator-onDataReady" class="headerlink" title="步骤56：SourceGenerator#onDataReady()"></a>步骤56：SourceGenerator#onDataReady()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">public void onDataReady(Object data) &#123;</span><br><span class="line">    DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();</span><br><span class="line">    if (data != null &amp;&amp; diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) &#123;</span><br><span class="line">        dataToCache = data;</span><br><span class="line">        cb.reschedule();</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,</span><br><span class="line">                loadData.fetcher.getDataSource(), originalKey);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>拿到网络请求结果之后，第3行，条件都满足，这已经解释过了，第4行，<code>dataToCache = data</code>，<code>SourceGenerator</code>中的成员变量<code>dataToCache</code>也赋值了。第5行，<code>cb.reschedule()</code>，这个cb是调用<code>SourceGenerator</code>的构造方法时传入的，是<code>DecodeJob</code>对象。所以接下来再次执行步骤52,53,54，不过需要注意的是，再次执行<code>SourceGenerator#startNext()</code>的时候，流程不一样了，接下来主要是网络数据的缓存和解码操作，贴一下步骤54的第2行</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">if (dataToCache != null) &#123;</span><br><span class="line">    Object data = dataToCache;</span><br><span class="line">    dataToCache = null;</span><br><span class="line">    cacheData(data);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>之前说过，<code>dataToCache</code>是null，但现在经过此步骤之后，不再是null了，接着会走<code>cacheData(data);</code>逻辑</p>
<h2 id="步骤57：SourceGenerator-cacheData"><a href="#步骤57：SourceGenerator-cacheData" class="headerlink" title="步骤57：SourceGenerator#cacheData()"></a>步骤57：SourceGenerator#cacheData()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">private void cacheData(Object dataToCache) &#123;</span><br><span class="line">    long startTime = LogTime.getLogTime();</span><br><span class="line">    try &#123;</span><br><span class="line">        Encoder&lt;Object&gt; encoder = helper.getSourceEncoder(dataToCache);</span><br><span class="line">        DataCacheWriter&lt;Object&gt; writer =</span><br><span class="line">                new DataCacheWriter&lt;&gt;(encoder, dataToCache, helper.getOptions());</span><br><span class="line">        originalKey = new DataCacheKey(loadData.sourceKey, helper.getSignature());</span><br><span class="line">        helper.getDiskCache().put(originalKey, writer);</span><br><span class="line">        if (Log.isLoggable(TAG, Log.VERBOSE)) &#123;</span><br><span class="line">            Log.v(TAG, &quot;Finished encoding source to cache&quot;</span><br><span class="line">                    + &quot;, key: &quot; + originalKey</span><br><span class="line">                    + &quot;, data: &quot; + dataToCache</span><br><span class="line">                    + &quot;, encoder: &quot; + encoder</span><br><span class="line">                    + &quot;, duration: &quot; + LogTime.getElapsedMillis(startTime));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; finally &#123;</span><br><span class="line">        loadData.fetcher.cleanup();</span><br><span class="line">    &#125;</span><br><span class="line">    sourceCacheGenerator =</span><br><span class="line">            new DataCacheGenerator(Collections.singletonList(loadData.sourceKey), helper, this);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里简单看下第8行，初始化缓存key，然后put对应的writer，第19和20行，初始化另一个成员变量<code>sourceCacheGenerator = new DataCacheGenerator(Collections.singletonList(loadData.sourceKey)</code>，接着继续执行步骤54第7到第9行</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">if (sourceCacheGenerator != null &amp;&amp; sourceCacheGenerator.startNext()) &#123;</span><br><span class="line">    return true;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里第一个条件成立，主要看第二个条件，<code>sourceCacheGenerator.startNext()</code>，也就是再回到步骤50，只不过条件不一样了。这里再分析一下</p>
<h2 id="步骤58：DataCacheGenerator-startNext"><a href="#步骤58：DataCacheGenerator-startNext" class="headerlink" title="步骤58：DataCacheGenerator#startNext()"></a>步骤58：DataCacheGenerator#startNext()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">public boolean startNext() &#123;</span><br><span class="line">    while (modelLoaders == null || !hasNextModelLoader()) &#123;</span><br><span class="line">        sourceIdIndex++;</span><br><span class="line">        if (sourceIdIndex &gt;= cacheKeys.size()) &#123;</span><br><span class="line">            return false;</span><br><span class="line">        &#125;</span><br><span class="line">        Key sourceId = cacheKeys.get(sourceIdIndex);</span><br><span class="line">        @SuppressWarnings(&quot;PMD.AvoidInstantiatingObjectsInLoops&quot;)</span><br><span class="line">        Key originalKey = new DataCacheKey(sourceId, helper.getSignature());</span><br><span class="line">        cacheFile = helper.getDiskCache().get(originalKey);</span><br><span class="line">        if (cacheFile != null) &#123;</span><br><span class="line">            this.sourceKey = sourceId;</span><br><span class="line">            modelLoaders = helper.getModelLoaders(cacheFile);</span><br><span class="line">            modelLoaderIndex = 0;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    loadData = null;</span><br><span class="line">    boolean started = false;</span><br><span class="line">    while (!started &amp;&amp; hasNextModelLoader()) &#123;</span><br><span class="line">        ModelLoader&lt;File, ?&gt; modelLoader = modelLoaders.get(modelLoaderIndex++);</span><br><span class="line">        loadData =</span><br><span class="line">                modelLoader.buildLoadData(cacheFile, helper.getWidth(), helper.getHeight(),</span><br><span class="line">                        helper.getOptions());</span><br><span class="line">        if (loadData != null &amp;&amp; helper.hasLoadPath(loadData.fetcher.getDataClass())) &#123;</span><br><span class="line">            started = true;</span><br><span class="line">            loadData.fetcher.loadData(helper.getPriority(), this);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return started;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第2行，判断条件，因为这个<code>DataCacheGenerator</code>对象也是刚刚初始化的对象，所以<code>modelLoaders</code>是null，条件成立之后，继续看第9和第10行，因为步骤57做了put()操作，所以这里第10行的get()方法是有值的，接着第13行，为成员变量<code>modelLoaders</code>赋值，这个<code>modelLoaders</code>与之前的提到的<code>modelClass = String.class</code>的集合不一样，这次是一个<code>modelClass = File.class的modelLoader</code>的集合。这里直接给出结果</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ByteBufferFileLoader</span><br><span class="line">FileLoader</span><br><span class="line">FileLoader</span><br><span class="line">UnitModelLoader</span><br></pre></td></tr></table></figure>
<p>总共有4个。此时第一次循环结束，再次判断while条件时，<code>modelLoaders</code>不再是null，条件不满足，跳出循环。</p>
<p>接着第20行，又是一个循环，第22行，23行，<code>modelLoader.buildLoadData(cacheFile,helper.getWidth(),helper.getHeight(),helper.getOptions())</code>又是<code>buildLoadData()</code>方法，与上次逻辑都是一样的，就不分析了。接着第25行，两个判断条件都是true，且第二个条件对主流程没啥影响，这里直接看第27行，<code>loadData.fetcher.loadData()</code>，这里的<code>loadData.fetcher</code>是什么，是上方分析的<code>ByteBufferFileLoader</code>。</p>
<p>ByteBufferFileLoader$ByteBufferFetcher#loadData()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">public void loadData(@NonNull Priority priority,</span><br><span class="line">                     @NonNull DataCallback&lt;? super ByteBuffer&gt; callback) &#123;</span><br><span class="line">    ByteBuffer result;</span><br><span class="line">    try &#123;</span><br><span class="line">        result = ByteBufferUtil.fromFile(file);</span><br><span class="line">    &#125; catch (IOException e) &#123;</span><br><span class="line">        if (Log.isLoggable(TAG, Log.DEBUG)) &#123;</span><br><span class="line">            Log.d(TAG, &quot;Failed to obtain ByteBuffer for file&quot;, e);</span><br><span class="line">        &#125;</span><br><span class="line">        callback.onLoadFailed(e);</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line">    callback.onDataReady(result);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第5行，<code>ByteBufferUtil.fromFile()</code>同样是文件相关操作，就不细看了，接着第13行，<code>callback.onDataReady()</code>通过回调往上层返回结果。下方是<code>DataCacheGenerator#onDataReady()</code>方法，cb指向<code>SourceGeneraotr</code>，因为我们是从步骤57来到这里的。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public void onDataReady(Object data) &#123;</span><br><span class="line">    cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.DATA_DISK_CACHE, sourceKey);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><code>loadData()</code>方法结束后，步骤58也结束，最终<code>return true；</code>那么步骤57第2段代码第2行，也<code>return true；</code></p>
<p>SourceGeneraotr#onDataFetcherReady()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher&lt;?&gt; fetcher,</span><br><span class="line">                               DataSource dataSource, Key attemptedKey) &#123;</span><br><span class="line">    cb.onDataFetcherReady(sourceKey, data, fetcher, loadData.fetcher.getDataSource(), sourceKey);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上方第3行，cb指向<code>DecodeJob</code></p>
<h2 id="步骤59：DecodeJob-onDataFetcherReady"><a href="#步骤59：DecodeJob-onDataFetcherReady" class="headerlink" title="步骤59：DecodeJob#onDataFetcherReady()"></a>步骤59：DecodeJob#onDataFetcherReady()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher&lt;?&gt; fetcher,</span><br><span class="line">                               DataSource dataSource, Key attemptedKey) &#123;</span><br><span class="line">    this.currentSourceKey = sourceKey;</span><br><span class="line">    this.currentData = data;</span><br><span class="line">    this.currentFetcher = fetcher;</span><br><span class="line">    this.currentDataSource = dataSource;</span><br><span class="line">    this.currentAttemptingKey = attemptedKey;</span><br><span class="line">    if (Thread.currentThread() != currentThread) &#123;</span><br><span class="line">        runReason = RunReason.DECODE_DATA;</span><br><span class="line">        callback.reschedule(this);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        GlideTrace.beginSection(&quot;DecodeJob.decodeFromRetrievedData&quot;);</span><br><span class="line">        try &#123;</span><br><span class="line">            decodeFromRetrievedData();</span><br><span class="line">        &#125; finally &#123;</span><br><span class="line">            GlideTrace.endSection();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第8行到第10行，判断两个线程是否相等，这里其实是相等的，那么走else分支，第14行，<code>decodeFromRetrievedData()</code></p>
<p>DecodeJob#decodeFromRetrievedData()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">private void decodeFromRetrievedData() &#123;</span><br><span class="line">    if (Log.isLoggable(TAG, Log.VERBOSE)) &#123;</span><br><span class="line">        logWithTimeAndKey(&quot;Retrieved data&quot;, startFetchTime,</span><br><span class="line">                &quot;data: &quot; + currentData</span><br><span class="line">                        + &quot;, cache key: &quot; + currentSourceKey</span><br><span class="line">                        + &quot;, fetcher: &quot; + currentFetcher);</span><br><span class="line">    &#125;</span><br><span class="line">    Resource&lt;R&gt; resource = null;</span><br><span class="line">    try &#123;</span><br><span class="line">        resource = decodeFromData(currentFetcher, currentData, currentDataSource);</span><br><span class="line">    &#125; catch (GlideException e) &#123;</span><br><span class="line">        e.setLoggingDetails(currentAttemptingKey, currentDataSource);</span><br><span class="line">        throwables.add(e);</span><br><span class="line">    &#125;</span><br><span class="line">    if (resource != null) &#123;</span><br><span class="line">        notifyEncodeAndRelease(resource, currentDataSource);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        runGenerators();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上方第10行，<code>decodeFromData()；</code></p>
<p>DecodeJob#decodeFromData()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">private &lt;Data&gt; Resource&lt;R&gt; decodeFromData(DataFetcher&lt;?&gt; fetcher, Data data,</span><br><span class="line">                                          DataSource dataSource) throws GlideException &#123;</span><br><span class="line">    try &#123;</span><br><span class="line">        if (data == null) &#123;</span><br><span class="line">            return null;</span><br><span class="line">        &#125;</span><br><span class="line">        long startTime = LogTime.getLogTime();</span><br><span class="line">        Resource&lt;R&gt; result = decodeFromFetcher(data, dataSource);</span><br><span class="line">        if (Log.isLoggable(TAG, Log.VERBOSE)) &#123;</span><br><span class="line">            logWithTimeAndKey(&quot;Decoded result &quot; + result, startTime);</span><br><span class="line">        &#125;</span><br><span class="line">        return result;</span><br><span class="line">    &#125; finally &#123;</span><br><span class="line">        fetcher.cleanup();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上方第8行<code>decodeFromFetcher()</code></p>
<h2 id="步骤-60：DecodeJob-decodeFromFetcher"><a href="#步骤-60：DecodeJob-decodeFromFetcher" class="headerlink" title="步骤 60：DecodeJob#decodeFromFetcher()"></a>步骤 60：DecodeJob#decodeFromFetcher()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">private &lt;Data&gt; Resource&lt;R&gt; decodeFromFetcher(Data data, DataSource dataSource)</span><br><span class="line">    throws GlideException &#123;</span><br><span class="line">  LoadPath&lt;Data, ?, R&gt; path = decodeHelper.getLoadPath((Class&lt;Data&gt;) data.getClass());</span><br><span class="line">  return runLoadPath(data, dataSource, path);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第3行，又要和<code>DecodeHelper</code>相关了，这次调用的是<code>DecodeHelper#getLoadPath()</code>方法，具体代码如下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;Data&gt; LoadPath&lt;Data, ?, Transcode&gt; getLoadPath(Class&lt;Data&gt; dataClass) &#123;</span><br><span class="line">  return glideContext.getRegistry().getLoadPath(dataClass, resourceClass, transcodeClass);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第2行，看到这个<code>glideContext.getRegistry()</code>大家就有经验了，是<code>Registry</code>对象，用于<code>Glide</code>的初始化配置<code>getLoadPath</code>的结果我们就不看了，继续看第一段代码的第4行，<code>runLoadPath()</code>方法</p>
<p>DecodeJob#runLoadPath()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">private &lt;Data, ResourceType&gt; Resource&lt;R&gt; runLoadPath(Data data, DataSource dataSource,</span><br><span class="line">                                                     LoadPath&lt;Data, ResourceType, R&gt; path) throws GlideException &#123;</span><br><span class="line">    Options options = getOptionsWithHardwareConfig(dataSource);</span><br><span class="line">    DataRewinder&lt;Data&gt; rewinder = glideContext.getRegistry().getRewinder(data);</span><br><span class="line">    try &#123;</span><br><span class="line">        // ResourceType in DecodeCallback below is required for compilation to work with gradle.</span><br><span class="line">        return path.load(</span><br><span class="line">                rewinder, options, width, height, new DecodeCallback&lt;ResourceType&gt;(dataSource));</span><br><span class="line">    &#125; finally &#123;</span><br><span class="line">        rewinder.cleanup();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第7行，<code>path.load()；</code></p>
<h2 id="步骤61：LoadPath-load"><a href="#步骤61：LoadPath-load" class="headerlink" title="步骤61：LoadPath#load()"></a>步骤61：LoadPath#load()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">public Resource&lt;Transcode&gt; load(DataRewinder&lt;Data&gt; rewinder, @NonNull Options options, int width,</span><br><span class="line">                                int height, DecodePath.DecodeCallback&lt;ResourceType&gt; decodeCallback) throws GlideException &#123;</span><br><span class="line">    List&lt;Throwable&gt; throwables = Preconditions.checkNotNull(listPool.acquire());</span><br><span class="line">    try &#123;</span><br><span class="line">        return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);</span><br><span class="line">    &#125; finally &#123;</span><br><span class="line">        listPool.release(throwables);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第5行，<code>loadWithExceptionList()</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">private Resource&lt;Transcode&gt; loadWithExceptionList(DataRewinder&lt;Data&gt; rewinder,</span><br><span class="line">                                                  @NonNull Options options,</span><br><span class="line">                                                  int width, int height, DecodePath.DecodeCallback&lt;ResourceType&gt; decodeCallback,</span><br><span class="line">                                                  List&lt;Throwable&gt; exceptions) throws GlideException &#123;</span><br><span class="line">    Resource&lt;Transcode&gt; result = null;</span><br><span class="line">    //noinspection ForLoopReplaceableByForEach to improve perf</span><br><span class="line">    for (int i = 0, size = decodePaths.size(); i &lt; size; i++) &#123;</span><br><span class="line">        DecodePath&lt;Data, ResourceType, Transcode&gt; path = decodePaths.get(i);</span><br><span class="line">        try &#123;</span><br><span class="line">            result = path.decode(rewinder, width, height, options, decodeCallback);</span><br><span class="line">        &#125; catch (GlideException e) &#123;</span><br><span class="line">            exceptions.add(e);</span><br><span class="line">        &#125;</span><br><span class="line">        if (result != null) &#123;</span><br><span class="line">            break;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    if (result == null) &#123;</span><br><span class="line">        throw new GlideException(failureMessage, new ArrayList&lt;&gt;(exceptions));</span><br><span class="line">    &#125;</span><br><span class="line">    return result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上方第7行，遍历<code>decodePaths</code>集合，然后第10行，<code>path.decode()</code>这里终于看到结果了，最终在21行返回结果。这里就不带大家去看<code>decode</code>操作了，先完成主要流程。其实这一步结束，返回的是一个<code>Resource&lt;Transcode&gt;</code>对象，还不是真正意义上的<code>Bitmap</code>或者<code>Drawable</code>，回到步骤59的第二段代码第16行，获取到<code>resource</code>之后，调用<code>notifyEncodeAndRelease();</code></p>
<h2 id="步骤62：DecodeJob-notifyEncodeAndRelease"><a href="#步骤62：DecodeJob-notifyEncodeAndRelease" class="headerlink" title="步骤62：DecodeJob#notifyEncodeAndRelease()"></a>步骤62：DecodeJob#notifyEncodeAndRelease()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">private void notifyEncodeAndRelease(Resource&lt;R&gt; resource, DataSource dataSource) &#123;</span><br><span class="line">    if (resource instanceof Initializable) &#123;</span><br><span class="line">        ((Initializable) resource).initialize();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    Resource&lt;R&gt; result = resource;</span><br><span class="line">    LockedResource&lt;R&gt; lockedResource = null;</span><br><span class="line">    if (deferredEncodeManager.hasResourceToEncode()) &#123;</span><br><span class="line">        lockedResource = LockedResource.obtain(resource);</span><br><span class="line">        result = lockedResource;</span><br><span class="line">    &#125;</span><br><span class="line">    notifyComplete(result, dataSource);</span><br><span class="line">    stage = Stage.ENCODE;</span><br><span class="line">    try &#123;</span><br><span class="line">        if (deferredEncodeManager.hasResourceToEncode()) &#123;</span><br><span class="line">            deferredEncodeManager.encode(diskCacheProvider, options);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; finally &#123;</span><br><span class="line">        if (lockedResource != null) &#123;</span><br><span class="line">            lockedResource.unlock();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    onEncodeComplete();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>看这一步骤的名字就知道，decode结束了，接下来就是encode阶段了，第12行有个<code>notifyComplete()</code>，第23行还有个<code>onEncodeComplete()</code>，先来看<code>DecodeJob#notifyComplete()</code>做了什么</p>
<h2 id="步骤63：DecodeJob-notifyComplete"><a href="#步骤63：DecodeJob-notifyComplete" class="headerlink" title="步骤63：DecodeJob#notifyComplete()"></a>步骤63：DecodeJob#notifyComplete()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">private void notifyComplete(Resource&lt;R&gt; resource, DataSource dataSource) &#123;</span><br><span class="line">    setNotifiedOrThrow();</span><br><span class="line">    callback.onResourceReady(resource, dataSource);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第3行，又是<code>callback</code>，一般<code>callback</code>都是调用初始化方法的时候赋值的，这里实质上是<code>EngineJob</code>对象，因为<code>DecodeJob</code>是在<code>EngineJob</code>中初始化的。</p>
<p>EngineJob#onResourceReady()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">private static final Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper(), new EngineJob.MainThreadCallback());</span><br><span class="line"></span><br><span class="line">public void onResourceReady(Resource&lt;R&gt; resource, DataSource dataSource) &#123;</span><br><span class="line">    this.resource = resource;</span><br><span class="line">    this.dataSource = dataSource;</span><br><span class="line">    MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里看到熟悉的代码了，第6行，<code>MAIN_THREAD_HANDLER.obtainMessage()</code>，这个<code>handler</code>是主线程中的<code>handler</code>，代表子线程结束，要开始转向UI线程了。消息标志位是<code>MSG_COMPLETE</code>，我们来找一下<code>handlerMessage()</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">private static class MainThreadCallback implements Handler.Callback &#123;</span><br><span class="line"></span><br><span class="line">    @Synthetic</span><br><span class="line">    @SuppressWarnings(&quot;WeakerAccess&quot;)</span><br><span class="line">    MainThreadCallback() &#123; &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public boolean handleMessage(Message message) &#123;</span><br><span class="line">        EngineJob&lt;?&gt; job = (EngineJob&lt;?&gt;) message.obj;</span><br><span class="line">        switch (message.what) &#123;</span><br><span class="line">            case MSG_COMPLETE:</span><br><span class="line">                job.handleResultOnMainThread();</span><br><span class="line">                break;</span><br><span class="line">            case MSG_EXCEPTION:</span><br><span class="line">                job.handleExceptionOnMainThread();</span><br><span class="line">                break;</span><br><span class="line">            case MSG_CANCELLED:</span><br><span class="line">                job.handleCancelledOnMainThread();</span><br><span class="line">                break;</span><br><span class="line">            default:</span><br><span class="line">                throw new IllegalStateException(&quot;Unrecognized message: &quot; + message.what);</span><br><span class="line">        &#125;</span><br><span class="line">        return true;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>上方第12行，处理了<code>MSG_COMPLETE</code>消息，调用<code>job.handleResultOnMainThread()</code>方法，这个job指向<code>EngineJob</code>，来到<code>EngineJob#handleResultOnMainThread()</code></p>
<h2 id="步骤64：EngineJob-handleResultOnMainThread"><a href="#步骤64：EngineJob-handleResultOnMainThread" class="headerlink" title="步骤64：EngineJob#handleResultOnMainThread()"></a>步骤64：EngineJob#handleResultOnMainThread()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">void handleResultOnMainThread() &#123;</span><br><span class="line">    stateVerifier.throwIfRecycled();</span><br><span class="line">    if (isCancelled) &#123;</span><br><span class="line">        resource.recycle();</span><br><span class="line">        release(false /*isRemovedFromQueue*/);</span><br><span class="line">        return;</span><br><span class="line">    &#125; else if (cbs.isEmpty()) &#123;</span><br><span class="line">        throw new IllegalStateException(&quot;Received a resource without any callbacks to notify&quot;);</span><br><span class="line">    &#125; else if (hasResource) &#123;</span><br><span class="line">        throw new IllegalStateException(&quot;Already have resource&quot;);</span><br><span class="line">    &#125;</span><br><span class="line">    engineResource = engineResourceFactory.build(resource, isCacheable);</span><br><span class="line">    hasResource = true;</span><br><span class="line">    engineResource.acquire();</span><br><span class="line">    listener.onEngineJobComplete(this, key, engineResource);</span><br><span class="line">    for (int i = 0, size = cbs.size(); i &lt; size; i++) &#123;</span><br><span class="line">        ResourceCallback cb = cbs.get(i);</span><br><span class="line">        if (!isInIgnoredCallbacks(cb)) &#123;</span><br><span class="line">            engineResource.acquire();</span><br><span class="line">            cb.onResourceReady(engineResource, dataSource);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    engineResource.release();</span><br><span class="line">    release(false /*isRemovedFromQueue*/);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>有两个回调第15行，<code>listener.onEngineJobComplete(this, key, engineResource);</code>还有就是for循环里面的第20行，<code>cb.onResourceReady(engineResource, dataSource);</code>先来看看第一个，这里的<code>listener</code>是初始化<code>EngineJob</code>的时候传入的，一步一步可以找到<code>Engine</code>的构造方法，这个<code>listener</code>是<code>Engine</code>本身</p>
<h2 id="步骤65：Engine-onEngineJobComplete"><a href="#步骤65：Engine-onEngineJobComplete" class="headerlink" title="步骤65：Engine#onEngineJobComplete()"></a>步骤65：Engine#onEngineJobComplete()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">public void onEngineJobComplete(EngineJob&lt;?&gt; engineJob, Key key, EngineResource&lt;?&gt; resource) &#123;</span><br><span class="line">    Util.assertMainThread();</span><br><span class="line">    if (resource != null) &#123;</span><br><span class="line">        resource.setResourceListener(key, this);</span><br><span class="line">        if (resource.isCacheable()) &#123;</span><br><span class="line">            activeResources.activate(key, resource);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    jobs.removeIfCurrent(key, engineJob);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第4行，<code>resource.setResourceListener(key, this)</code>，就是一个set操作，第5行，判断资源是否可以被缓存，这里很显然是true，进而来到第6行，<code>activeResources.activate(key, resource)；</code>开始执行内存缓存</p>
<p>ActiveResources#activate()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">void activate(Key key, EngineResource&lt;?&gt; resource) &#123;</span><br><span class="line">    ActiveResources.ResourceWeakReference toPut =</span><br><span class="line">            new ActiveResources.ResourceWeakReference(</span><br><span class="line">                    key,</span><br><span class="line">                    resource,</span><br><span class="line">                    getReferenceQueue(),</span><br><span class="line">                    isActiveResourceRetentionAllowed);</span><br><span class="line"></span><br><span class="line">    ActiveResources.ResourceWeakReference removed = activeEngineResources.put(key, toPut);</span><br><span class="line">    if (removed != null) &#123;</span><br><span class="line">        removed.reset();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第9行，<code>activeEngineResources.put()</code>，这个<code>activeEngineResources</code>其实就是Map，这里的<code>activeEngineResources</code>其实是内存缓存，还用了<code>WeakReference</code>；方法执行结束，内存缓存有了。再看本步骤第一段第9行，<code>jobs.removeIfCurrent(key, engineJob);</code>其实也是map操作，就不关心了。</p>
<h2 id="步骤66：回到步骤64"><a href="#步骤66：回到步骤64" class="headerlink" title="步骤66：回到步骤64"></a>步骤66：回到步骤64</h2><p>回到步骤64，我们继续分析留下的第二个回调，步骤64的第16到22行，代码如下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">for (int i = 0, size = cbs.size(); i &lt; size; i++) &#123;</span><br><span class="line">    ResourceCallback cb = cbs.get(i);</span><br><span class="line">    if (!isInIgnoredCallbacks(cb)) &#123;</span><br><span class="line">        engineResource.acquire();</span><br><span class="line">        cb.onResourceReady(engineResource, dataSource);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第1行，这里遍历的cbs是什么呢，我们来看下cbs在哪里调用add方法的，找到了<code>EngineJob#addCallback()</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">void addCallback(ResourceCallback cb) &#123;</span><br><span class="line">    Util.assertMainThread();</span><br><span class="line">    stateVerifier.throwIfRecycled();</span><br><span class="line">    if (hasResource) &#123;</span><br><span class="line">        cb.onResourceReady(engineResource, dataSource);</span><br><span class="line">    &#125; else if (hasLoadFailed) &#123;</span><br><span class="line">        cb.onLoadFailed(exception);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        cbs.add(cb);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><code>EngineJob#addCallback()</code>方法又是在哪里调用呢？我们回到步骤15的<code>Engine#load()</code>方法，是初始化<code>EngineJob</code>和<code>DecodeJob</code>的地方，步骤15第75行，发现了<code>engineJob.addCallback(cb);</code>再看步骤14的第17行和第35行，可以知道，这个<code>callback</code>就是<code>SingleRequest</code></p>
<h2 id="步骤67：SingleRequest-onResourceReady"><a href="#步骤67：SingleRequest-onResourceReady" class="headerlink" title="步骤67：SingleRequest#onResourceReady()"></a>步骤67：SingleRequest#onResourceReady()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">public void onResourceReady(Resource&lt;?&gt; resource, DataSource dataSource) &#123;</span><br><span class="line">    stateVerifier.throwIfRecycled();</span><br><span class="line">    loadStatus = null;</span><br><span class="line">    if (resource == null) &#123;</span><br><span class="line">        GlideException exception = new GlideException(&quot;Expected to receive a Resource&lt;R&gt; with an &quot;</span><br><span class="line">                + &quot;object of &quot; + transcodeClass + &quot; inside, but instead got null.&quot;);</span><br><span class="line">        onLoadFailed(exception);</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line">    Object received = resource.get();</span><br><span class="line">    if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) &#123;</span><br><span class="line">        releaseResource(resource);</span><br><span class="line">        GlideException exception = new GlideException(&quot;Expected to receive an object of &quot;</span><br><span class="line">                + transcodeClass + &quot; but instead&quot; + &quot; got &quot;</span><br><span class="line">                + (received != null ? received.getClass() : &quot;&quot;) + &quot;&#123;&quot; + received + &quot;&#125; inside&quot; + &quot; &quot;</span><br><span class="line">                + &quot;Resource&#123;&quot; + resource + &quot;&#125;.&quot;</span><br><span class="line">                + (received != null ? &quot;&quot; : &quot; &quot; + &quot;To indicate failure return a null Resource &quot;</span><br><span class="line">                + &quot;object, rather than a Resource object containing null data.&quot;));</span><br><span class="line">        onLoadFailed(exception);</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    if (!canSetResource()) &#123;</span><br><span class="line">        releaseResource(resource);</span><br><span class="line">        // We can&apos;t put the status to complete before asking canSetResource().</span><br><span class="line">        status = Status.COMPLETE;</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line">    onResourceReady((Resource&lt;R&gt;) resource, (R) received, dataSource);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>跳过第7行，第19行的<code>onLoadFailed()</code>，直接看第29行，<code>onResourceReady()</code>，是另一个重载方法</p>
<h2 id="步骤68：SingleRequest-onResourceReady"><a href="#步骤68：SingleRequest-onResourceReady" class="headerlink" title="步骤68：SingleRequest#onResourceReady()"></a>步骤68：SingleRequest#onResourceReady()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">private void onResourceReady(Resource&lt;R&gt; resource, R result, DataSource dataSource) &#123;</span><br><span class="line">    // We must call isFirstReadyResource before setting status.</span><br><span class="line">    boolean isFirstResource = isFirstReadyResource();</span><br><span class="line">    status = Status.COMPLETE;</span><br><span class="line">    this.resource = resource;</span><br><span class="line"></span><br><span class="line">    if (glideContext.getLogLevel() &lt;= Log.DEBUG) &#123;</span><br><span class="line">        Log.d(GLIDE_TAG, &quot;Finished loading &quot; + result.getClass().getSimpleName() + &quot; from &quot;</span><br><span class="line">                + dataSource + &quot; for &quot; + model + &quot; with size [&quot; + width + &quot;x&quot; + height + &quot;] in &quot;</span><br><span class="line">                + LogTime.getElapsedMillis(startTime) + &quot; ms&quot;);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    isCallingCallbacks = true;</span><br><span class="line">    try &#123;</span><br><span class="line">        boolean anyListenerHandledUpdatingTarget = false;</span><br><span class="line">        if (requestListeners != null) &#123;</span><br><span class="line">            for (RequestListener&lt;R&gt; listener : requestListeners) &#123;</span><br><span class="line">                anyListenerHandledUpdatingTarget |=</span><br><span class="line">                        listener.onResourceReady(result, model, target, dataSource, isFirstResource);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        anyListenerHandledUpdatingTarget |=</span><br><span class="line">                targetListener != null</span><br><span class="line">                        &amp;&amp; targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);</span><br><span class="line"></span><br><span class="line">        if (!anyListenerHandledUpdatingTarget) &#123;</span><br><span class="line">            Transition&lt;? super R&gt; animation =</span><br><span class="line">                    animationFactory.build(dataSource, isFirstResource);</span><br><span class="line">            target.onResourceReady(result, animation);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; finally &#123;</span><br><span class="line">        isCallingCallbacks = false;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    notifyLoadSuccess();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第29行，<code>target.onResourceReady()</code>，这个<code>target</code>是谁呢，其实就是在步骤7我们说过的<code>DrawableImageViewTarget</code>对象，如果我们来到<code>DrawableImageViewTarget</code>类的话，会发现并没有<code>onResourceReady()</code>方法，其实是在它的父类<code>ImageViewTarget</code>中，第35行是其他listener的回调，这里不关心了</p>
<h2 id="步骤69：ImageViewTarget-onResourceReady"><a href="#步骤69：ImageViewTarget-onResourceReady" class="headerlink" title="步骤69：ImageViewTarget#onResourceReady()"></a>步骤69：ImageViewTarget#onResourceReady()</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">public void onResourceReady(@NonNull Z resource, @Nullable Transition&lt;? super Z&gt; transition) &#123;</span><br><span class="line">    if (transition == null || !transition.transition(resource, this)) &#123;</span><br><span class="line">        setResourceInternal(resource);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        maybeUpdateAnimatable(resource);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>第2行判断<code>transition</code>是否为null，很显然是true，接着会走<code>setResourceInternal()</code>方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">private void setResourceInternal(@Nullable Z resource) &#123;</span><br><span class="line">    setResource(resource);</span><br><span class="line">    maybeUpdateAnimatable(resource);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">protected abstract void setResource(@Nullable Z resource);</span><br></pre></td></tr></table></figure>
<p>第2行，<code>setResource(resource);</code>这里是个抽象方法，交给子类实现，我们回到<code>DrawableImageViewTarget</code>对象中，查看<code>setResource()</code>方法</p>
<p>DrawableImageViewTarget#setResource()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">protected void setResource(@Nullable Drawable resource) &#123;</span><br><span class="line">  view.setImageDrawable(resource);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>终于要结束了，第2行<code>view.setImageDrawable(resource);</code>这是Android原生API，<code>ImageView</code>可以显示图片了</p>
<p>再回到步骤62的第23行，<code>onEncodeComplete()</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">private void onEncodeComplete() &#123;</span><br><span class="line">    if (releaseManager.onEncodeComplete()) &#123;</span><br><span class="line">        releaseInternal();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">private void releaseInternal() &#123;</span><br><span class="line">    releaseManager.reset();</span><br><span class="line">    deferredEncodeManager.clear();</span><br><span class="line">    decodeHelper.clear();</span><br><span class="line">    isCallbackNotified = false;</span><br><span class="line">    glideContext = null;</span><br><span class="line">    signature = null;</span><br><span class="line">    options = null;</span><br><span class="line">    priority = null;</span><br><span class="line">    loadKey = null;</span><br><span class="line">    callback = null;</span><br><span class="line">    stage = null;</span><br><span class="line">    currentGenerator = null;</span><br><span class="line">    currentThread = null;</span><br><span class="line">    currentSourceKey = null;</span><br><span class="line">    currentData = null;</span><br><span class="line">    currentDataSource = null;</span><br><span class="line">    currentFetcher = null;</span><br><span class="line">    startFetchTime = 0L;</span><br><span class="line">    isCancelled = false;</span><br><span class="line">    model = null;</span><br><span class="line">    throwables.clear();</span><br><span class="line">    pool.release(this);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>可以看到就是一些收尾的工作了。至此，所有流程已经结束了。</p>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/Glide/" rel="tag"># Glide</a>
          
        </div>
      

      
      
        <div class="post-widgets">
        
          <div class="wp_rating">
            <div id="wpac-rating"></div>
          </div>
        

        

        
        </div>
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2019/02/21/Glide(2)-基于Glide4.8的缓存原理分析/" rel="prev" title="Glide(2)-基于Glide4.8的缓存原理分析">
                Glide(2)-基于Glide4.8的缓存原理分析 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
            
              <p class="site-author-name" itemprop="name">lt19931203</p>
              <p class="site-description motion-element" itemprop="description">技术道路，勇于向前</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">2</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            

            
              
              
              <div class="site-state-item site-state-tags">
                
                  <span class="site-state-item-count">1</span>
                  <span class="site-state-item-name">标签</span>
                
              </div>
            

          </nav>

          

          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#序言"><span class="nav-number">1.</span> <span class="nav-text">序言</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Glide-with"><span class="nav-number">2.</span> <span class="nav-text">Glide.with()</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤1：Glide-with-返回了什么"><span class="nav-number">2.1.</span> <span class="nav-text">步骤1：Glide.with()返回了什么</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤2：RequestManager-get"><span class="nav-number">2.2.</span> <span class="nav-text">步骤2：RequestManager#get()</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Glide-with-load"><span class="nav-number">3.</span> <span class="nav-text">Glide.with().load()</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤3：RequestManager-load"><span class="nav-number">3.1.</span> <span class="nav-text">步骤3：RequestManager#load()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤4-：RequestBuilder-load"><span class="nav-number">3.2.</span> <span class="nav-text">步骤4 ：RequestBuilder#load()</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Glide-with-load-into"><span class="nav-number">4.</span> <span class="nav-text">Glide.with().load().into()</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤5：RequestBuilder-into"><span class="nav-number">4.1.</span> <span class="nav-text">步骤5：RequestBuilder#into()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤6：步骤5第32行"><span class="nav-number">4.2.</span> <span class="nav-text">步骤6：步骤5第32行</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤7：GlideContext-buildImageViewTarget"><span class="nav-number">4.3.</span> <span class="nav-text">步骤7：GlideContext#buildImageViewTarget()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤8：步骤5第38行"><span class="nav-number">4.4.</span> <span class="nav-text">步骤8：步骤5第38行</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤9：SingleRequest-obtain"><span class="nav-number">4.5.</span> <span class="nav-text">步骤9：SingleRequest#obtain()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤10：步骤5第60行"><span class="nav-number">4.6.</span> <span class="nav-text">步骤10：步骤5第60行</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤11：SingleRequest-begin"><span class="nav-number">4.7.</span> <span class="nav-text">步骤11：SingleRequest#begin()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤12：DrawableImageViewTarget-getSize"><span class="nav-number">4.8.</span> <span class="nav-text">步骤12：DrawableImageViewTarget#getSize()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤13：ViewTarget-getSize"><span class="nav-number">4.9.</span> <span class="nav-text">步骤13：ViewTarget#getSize()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤14：SingleRequest-onSizeReady-width-height"><span class="nav-number">4.10.</span> <span class="nav-text">步骤14：SingleRequest#onSizeReady(width, height);</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤15：Engine-load"><span class="nav-number">4.11.</span> <span class="nav-text">步骤15：Engine#load()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤16：EngineJob-start"><span class="nav-number">4.12.</span> <span class="nav-text">步骤16：EngineJob#start()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤17：DecodeJob-run"><span class="nav-number">4.13.</span> <span class="nav-text">步骤17：DecodeJob#run()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤18：DecodeJob-runWrapped"><span class="nav-number">4.14.</span> <span class="nav-text">步骤18：DecodeJob#runWrapped()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤19：DecodeJob-getNextStage"><span class="nav-number">4.15.</span> <span class="nav-text">步骤19：DecodeJob#getNextStage()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤20：DiskCacheStrategy-AUTOMATIC"><span class="nav-number">4.16.</span> <span class="nav-text">步骤20：DiskCacheStrategy#AUTOMATIC</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤21：DecodeJob-getNextGenerator"><span class="nav-number">4.17.</span> <span class="nav-text">步骤21：DecodeJob#getNextGenerator()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤22：DecodeJob-runGenerators"><span class="nav-number">4.18.</span> <span class="nav-text">步骤22：DecodeJob#runGenerators()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤23：ResourceCacheGenerator-startNext"><span class="nav-number">4.19.</span> <span class="nav-text">步骤23：ResourceCacheGenerator#startNext()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤24：DecodeHelper-getCacheKeys"><span class="nav-number">4.20.</span> <span class="nav-text">步骤24：DecodeHelper#getCacheKeys()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤25：DecodeHelper-getLoadData"><span class="nav-number">4.21.</span> <span class="nav-text">步骤25：DecodeHelper#getLoadData()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤26：Registry-getModelLoaders"><span class="nav-number">4.22.</span> <span class="nav-text">步骤26：Registry#getModelLoaders()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤27：ModelLoaderRegistry-getModelLoaders"><span class="nav-number">4.23.</span> <span class="nav-text">步骤27：ModelLoaderRegistry#getModelLoaders()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤28：ModelLoaderRegistry-getModelLoadersForClass"><span class="nav-number">4.24.</span> <span class="nav-text">步骤28：ModelLoaderRegistry#getModelLoadersForClass()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤29：MultiModelLoaderFactory-build"><span class="nav-number">4.25.</span> <span class="nav-text">步骤29：MultiModelLoaderFactory#build()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤30：MultiModelLoaderFactory-append"><span class="nav-number">4.26.</span> <span class="nav-text">步骤30：MultiModelLoaderFactory#append()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤31：ModelLoaderRegistry-append"><span class="nav-number">4.27.</span> <span class="nav-text">步骤31：ModelLoaderRegistry#append()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤32：Registry-append"><span class="nav-number">4.28.</span> <span class="nav-text">步骤32：Registry#append()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤33：Glide-…"><span class="nav-number">4.29.</span> <span class="nav-text">步骤33：Glide(…)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤34：回到步骤29"><span class="nav-number">4.30.</span> <span class="nav-text">步骤34：回到步骤29</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤35：Entry-handles"><span class="nav-number">4.31.</span> <span class="nav-text">步骤35：Entry#handles()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤36：MultiModelLoaderFactory-build"><span class="nav-number">4.32.</span> <span class="nav-text">步骤36：MultiModelLoaderFactory#build()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤37：MultiModelLoaderFactory-build-…"><span class="nav-number">4.33.</span> <span class="nav-text">步骤37：MultiModelLoaderFactory#build(…)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤38：MultiModelLoaderFactory-build-Entry"><span class="nav-number">4.34.</span> <span class="nav-text">步骤38：MultiModelLoaderFactory#build(Entry)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤39：分析目前结果"><span class="nav-number">4.35.</span> <span class="nav-text">步骤39：分析目前结果</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤40：Factory-build"><span class="nav-number">4.36.</span> <span class="nav-text">步骤40：Factory#build()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤41：回到步骤29，返回最终结果"><span class="nav-number">4.37.</span> <span class="nav-text">步骤41：回到步骤29，返回最终结果</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤42：回到步骤25"><span class="nav-number">4.38.</span> <span class="nav-text">步骤42：回到步骤25</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤43：StringLoader-buildLoadData"><span class="nav-number">4.39.</span> <span class="nav-text">步骤43：StringLoader#buildLoadData()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤44：MultiModelLoader-handles"><span class="nav-number">4.40.</span> <span class="nav-text">步骤44：MultiModelLoader#handles()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤45：MultiModelLoader-buildLoadData"><span class="nav-number">4.41.</span> <span class="nav-text">步骤45：MultiModelLoader#buildLoadData()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤46：回到步骤24"><span class="nav-number">4.42.</span> <span class="nav-text">步骤46：回到步骤24</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤47：DecodeHelper-getRegisteredResourceClasses"><span class="nav-number">4.43.</span> <span class="nav-text">步骤47：DecodeHelper#getRegisteredResourceClasses()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤48：回到步骤23"><span class="nav-number">4.44.</span> <span class="nav-text">步骤48：回到步骤23</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤49：DecodeJob-runGenerators"><span class="nav-number">4.45.</span> <span class="nav-text">步骤49：DecodeJob#runGenerators()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤50：DataCacheGenerator-startNext"><span class="nav-number">4.46.</span> <span class="nav-text">步骤50：DataCacheGenerator#startNext()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤51：回到步骤49执行循环"><span class="nav-number">4.47.</span> <span class="nav-text">步骤51：回到步骤49执行循环</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤52：DecodeJob-reschedule"><span class="nav-number">4.48.</span> <span class="nav-text">步骤52：DecodeJob#reschedule()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤53：EngineJob-reschedule"><span class="nav-number">4.49.</span> <span class="nav-text">步骤53：EngineJob#reschedule()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤54：SourceGenerator-startNext"><span class="nav-number">4.50.</span> <span class="nav-text">步骤54：SourceGenerator#startNext()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤55：HttpUrlFetcher-loadData"><span class="nav-number">4.51.</span> <span class="nav-text">步骤55：HttpUrlFetcher#loadData()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤56：SourceGenerator-onDataReady"><span class="nav-number">4.52.</span> <span class="nav-text">步骤56：SourceGenerator#onDataReady()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤57：SourceGenerator-cacheData"><span class="nav-number">4.53.</span> <span class="nav-text">步骤57：SourceGenerator#cacheData()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤58：DataCacheGenerator-startNext"><span class="nav-number">4.54.</span> <span class="nav-text">步骤58：DataCacheGenerator#startNext()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤59：DecodeJob-onDataFetcherReady"><span class="nav-number">4.55.</span> <span class="nav-text">步骤59：DecodeJob#onDataFetcherReady()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤-60：DecodeJob-decodeFromFetcher"><span class="nav-number">4.56.</span> <span class="nav-text">步骤 60：DecodeJob#decodeFromFetcher()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤61：LoadPath-load"><span class="nav-number">4.57.</span> <span class="nav-text">步骤61：LoadPath#load()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤62：DecodeJob-notifyEncodeAndRelease"><span class="nav-number">4.58.</span> <span class="nav-text">步骤62：DecodeJob#notifyEncodeAndRelease()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤63：DecodeJob-notifyComplete"><span class="nav-number">4.59.</span> <span class="nav-text">步骤63：DecodeJob#notifyComplete()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤64：EngineJob-handleResultOnMainThread"><span class="nav-number">4.60.</span> <span class="nav-text">步骤64：EngineJob#handleResultOnMainThread()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤65：Engine-onEngineJobComplete"><span class="nav-number">4.61.</span> <span class="nav-text">步骤65：Engine#onEngineJobComplete()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤66：回到步骤64"><span class="nav-number">4.62.</span> <span class="nav-text">步骤66：回到步骤64</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤67：SingleRequest-onResourceReady"><span class="nav-number">4.63.</span> <span class="nav-text">步骤67：SingleRequest#onResourceReady()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤68：SingleRequest-onResourceReady"><span class="nav-number">4.64.</span> <span class="nav-text">步骤68：SingleRequest#onResourceReady()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#步骤69：ImageViewTarget-onResourceReady"><span class="nav-number">4.65.</span> <span class="nav-text">步骤69：ImageViewTarget#onResourceReady()</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2019</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">lt19931203</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Gemini</a> v5.1.4</div>




        
<div class="busuanzi-count">
  <script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>

  
    <span class="site-uv">
      <i class="fa fa-user"></i>
      <span class="busuanzi-value" id="busuanzi_value_site_uv"></span>
      
    </span>
  

  
    <span class="site-pv">
      <i class="fa fa-eye"></i>
      <span class="busuanzi-value" id="busuanzi_value_site_pv"></span>
      
    </span>
  
</div>








        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
          <span id="scrollpercent"><span>0</span>%</span>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  
  <script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js"></script>
  <script>AV.initialize("", "");</script>
  <script>
    function showTime(Counter) {
      var query = new AV.Query(Counter);
      var entries = [];
      var $visitors = $(".leancloud_visitors");

      $visitors.each(function () {
        entries.push( $(this).attr("id").trim() );
      });

      query.containedIn('url', entries);
      query.find()
        .done(function (results) {
          var COUNT_CONTAINER_REF = '.leancloud-visitors-count';

          if (results.length === 0) {
            $visitors.find(COUNT_CONTAINER_REF).text(0);
            return;
          }

          for (var i = 0; i < results.length; i++) {
            var item = results[i];
            var url = item.get('url');
            var time = item.get('time');
            var element = document.getElementById(url);

            $(element).find(COUNT_CONTAINER_REF).text(time);
          }
          for(var i = 0; i < entries.length; i++) {
            var url = entries[i];
            var element = document.getElementById(url);
            var countSpan = $(element).find(COUNT_CONTAINER_REF);
            if( countSpan.text() == '') {
              countSpan.text(0);
            }
          }
        })
        .fail(function (object, error) {
          console.log("Error: " + error.code + " " + error.message);
        });
    }

    function addCount(Counter) {
      var $visitors = $(".leancloud_visitors");
      var url = $visitors.attr('id').trim();
      var title = $visitors.attr('data-flag-title').trim();
      var query = new AV.Query(Counter);

      query.equalTo("url", url);
      query.find({
        success: function(results) {
          if (results.length > 0) {
            var counter = results[0];
            counter.fetchWhenSave(true);
            counter.increment("time");
            counter.save(null, {
              success: function(counter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(counter.get('time'));
              },
              error: function(counter, error) {
                console.log('Failed to save Visitor num, with error message: ' + error.message);
              }
            });
          } else {
            var newcounter = new Counter();
            /* Set ACL */
            var acl = new AV.ACL();
            acl.setPublicReadAccess(true);
            acl.setPublicWriteAccess(true);
            newcounter.setACL(acl);
            /* End Set ACL */
            newcounter.set("title", title);
            newcounter.set("url", url);
            newcounter.set("time", 1);
            newcounter.save(null, {
              success: function(newcounter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(newcounter.get('time'));
              },
              error: function(newcounter, error) {
                console.log('Failed to create');
              }
            });
          }
        },
        error: function(error) {
          console.log('Error:' + error.code + " " + error.message);
        }
      });
    }

    $(function() {
      var Counter = AV.Object.extend("Counter");
      if ($('.leancloud_visitors').length == 1) {
        addCount(Counter);
      } else if ($('.post-title-link').length > 1) {
        showTime(Counter);
      }
    });
  </script>



  

  

  
  
  <script type="text/javascript">
  wpac_init = window.wpac_init || [];
  wpac_init.push({widget: 'Rating', id: ,
    el: 'wpac-rating',
    color: 'fc6423'
  });
  (function() {
    if ('WIDGETPACK_LOADED' in window) return;
    WIDGETPACK_LOADED = true;
    var mc = document.createElement('script');
    mc.type = 'text/javascript';
    mc.async = true;
    mc.src = '//embed.widgetpack.com/widget.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(mc, s.nextSibling);
  })();
  </script>


  

  

  

</body>
</html>
